diff --git a/SUMMARY.md b/SUMMARY.md index d5c9d86..bbf282f 100644 --- a/SUMMARY.md +++ b/SUMMARY.md @@ -42,6 +42,11 @@ * [realtime todo](./sailsjs/3_realtime_todo.md) - Week4 * [上課用練習](./react/week4_class_example.md) + * [Virtual Dom](./react/virtual_dom.md) +- Week5 + * [上課用練習](./react/week5_class_example.md) +- Week6 + * [style](./reactnative/style.md) * [SASS](./SASS/sass.md) - Week5 * [Redux](./redux/redux.md) @@ -51,3 +56,4 @@ * [browserHistory&hashHistory](./browserhistory_hashhistory/ebrowserhistory_hashhistory.md) - Week6 * [基本元件](./reactnative/basic_bomponents.md) +>>>>>>> upstream/master diff --git a/react/virtual_dom.md b/react/virtual_dom.md new file mode 100644 index 0000000..ec2a6c8 --- /dev/null +++ b/react/virtual_dom.md @@ -0,0 +1,36 @@ +#Virtual DOM + +##為何要使用Virtual Dom? + +DOM 操作的效能成本非常的高,React 為了解決開發者在手動操作 DOM 時可能造成的效能低落或失誤,建立了一套虛擬 DOM( Virtual DOM,以下簡稱 VDOM)的機制,程式記憶體中將有一份對應真正 DOM 的 VDOM 物件,以代管 UI 儲存的資料與邏輯。當一個 UI 因為資料改變而需要進行畫面變動的時候,React 會根據新的 UI 狀態重繪一份新的 VDOM Tree,並且與變動前的舊 VDOM Tree 以高效率的 Diff 演算法進行比對,然後其中的差異才會真正的由 React 自動幫你更新到實際的 DOM 上,反應出畫面的變更。 + +透過 VDOM 的機制,開發者將不必煩惱如何操作 DOM,而可以專心於撰寫 UI 的定義與互動邏輯。並且由於 React 能夠自動去最佳化的處理 DOM 操作,前端 UI 程式將可以有效的降低操作成本而達到優秀的效能。 + + +###從 Virtual DOM 生成DOM 帶來了一些好處 + +* 標籤之間的空格從一開始就被排除,不會帶來意外的空白元素的字符串被自動轉義,不會那麼容易導致代碼注入 + +* JSON 的Tree 很容易組合,組件化很自然就實現出來了 +同時,JavaScript 可以在 Node.js 和瀏覽器同時運行,能夠共享代碼同時得益於 DOM 會自動完成Diff 和 Patch,DOM 樹就能夠自動隨著數據改變進行更新,更新 DOM 。就像是 MVC 描述的那樣,Model 被更新,View 就跟著更新,就這麼簡單 + + +###Virtual DOM + +* 是一份純資料的 Tree 物件,對應到實際的 DOM + +* 是自定義 Component 提供了中介的虛擬層,讓開發者能描述 UI 樣貌與邏輯 + +我們透過定義 Component 來表達「UI 什麼情況該如何呈現」。而「要用什麼手段來達到這個畫面改變(如何操作 DOM)」 ,React 則會自動幫你做,而且絕大多數情況下都比你自己來要做的更好 + +###Single Source of Truth + +* UI 要長得如何,應當是取決於當時的 Model 資料以及 UI 狀態而決定 + +* 把畫面全部洗掉重新再畫,顯示結果通常一定是正確的 + +* 每次都重繪全部的實體 DOM 顯然是不可行,但是重繪 VDOM 則相對高效許多 + + +當畫面需要改變時,根據最新的 UI 狀態重繪出新的 VDOM Tree並與改變前的舊 VDOM Tree 進行全面式的比較與計算,其中新舊差異的地方,才真的會在實際的 DOM 上發生操作改變 + diff --git a/react/week5_class_example-copy.md b/react/week5_class_example-copy.md new file mode 100644 index 0000000..2d86bcf --- /dev/null +++ b/react/week5_class_example-copy.md @@ -0,0 +1,4 @@ +# 上課用練習 +請各位先將以下兩個專案 __fork 到自己的 github__,然後 `git clone` 並都 `npm install` + * [React Router Practice](https://github.com/tz5514/hellojs-react-router-practice) + * [Redux Practice](https://github.com/tz5514/hellojs-redux-practice) diff --git a/reactnative/pic.png b/reactnative/pic.png new file mode 100644 index 0000000..9be8f3b Binary files /dev/null and b/reactnative/pic.png differ diff --git a/reactnative/style.md b/reactnative/style.md new file mode 100644 index 0000000..5009484 --- /dev/null +++ b/reactnative/style.md @@ -0,0 +1,299 @@ +I##StyleSheet.create + +駝峰式的 CSS 屬性名稱 + +``` +const styles = StyleSheet.create({ + container: { + flex: 1, + justifyContent: 'center', + alignItems: 'center', + backgroundColor: '#F5FCFF', + }, +}); + +``` +類似CSS的樣式程式碼撰寫方式 + +##使用樣式 + +* 單樣式使用方式 + + `` + +* 使用多個樣式 + + `` + + 與 Object.assign 相同,若有衝突,右邊優先 + +* 以條件選擇樣式 + + `` + + 預設執行前項`styles.base`樣式,當後面`this.state.active`狀態改變為true或成立時執行後項`styles.active`的樣式 + + +##樣式變換 + +目標:按按鈕變換按鈕顏色 + +* 建立樣式 + +* 先在下方const styles內新增樣式blue和green,如下 + +``` +const styles = StyleSheet.create({ + blue:{ + backgroundColor: 'blue' + }, + green:{ + backgroundColor: 'green' + } +}); +``` + +* 建立按鈕 + +* 事件需匯入TouchableOpacity來產生按鈕,如下 + +``` +import { + TouchableOpacity +} from 'react-native'; +``` + +* 按鈕功能判斷 + +* 點擊改變true或false來判斷是否點擊來做顏色的變換 +在constructor(props)中設定active初值,如下 + +``` +constructor(props) { + super(props) + this.state = { + active: false, + } + } +``` + +* 設定onPress功能的狀態變化 + +``` + onPress = () => { + this.setState({active: !this.state.active}); + } +``` + + * 在render中顯示button的按鈕 + +``` + + + button + + +``` + +* 在onPress={this.onPress}加入樣式的變化判斷 + +``` +style={[styles.blue, this.state.active && styles.green]} +``` + +程式碼整段會變成如下 + +``` + + + button + + +``` + +說明```style={[styles.blue, this.state.active && styles.green]}``` + + 1. 畫面預設會先執行styles.blue + + 2. 按下按鈕後this.state.active成立變成true就會執行styles.green + + 3. 再按一下this.state.active變成false就會回到預設styles.blue + +所有程式碼 + +要複製直接套用記得把裡面有`app2`的改成你的檔名 + +``` +import React, { Component } from 'react'; +import { + AppRegistry, + StyleSheet, + Text, + View, + TouchableOpacity +} from 'react-native'; + +class app2 extends Component { + constructor(props) { + super(props) + this.state = { + active: false, + } + } + onPress = () => { + this.setState({active: !this.state.active}); + } + + render() { + return ( + + + + button + + + + style 樣式練習{'\n'} + 按按鈕變換按鈕顏色 + + + ); + } +} + +const styles = StyleSheet.create({ + container: { + flex: 1, + justifyContent: 'center', + alignItems: 'center', + backgroundColor: '#F5FCFF', + }, + instructions: { + textAlign: 'center', + color: '#333333', + marginBottom: 5, + }, + blue:{ + backgroundColor: 'blue' + }, + green:{ + backgroundColor: 'green' + } +}); + +AppRegistry.registerComponent('app2', () => app2); +``` + +##使用Flexbox布局 + +目標:畫面佈局與分割 + +* 排版方向,預設是 column +flexDirection 方向排版比例 + +將以下加入到render中 +畫面中會變成垂直2:1的顏色條(亮藍色:亮綠色) + +``` + + + View1 + + + View2 + + +``` + +###justifyContent & alignItems + +* justifyContent + + flexDirection方向的子元素排版 + + 能用的值:flex-start, center, flex-end, space-around, space-between + + +* alignItems + + 垂直 flexDirection 方向的子元素排版 + + 能用的值:flex-start, center, flex-end, stretch + +如果只要設定自己元素的排版用alignSelf + +例如:alignSelf:flex-start這是設定靠上對齊畫面中的分割 + +以下範例圖示 + +![](pic.png) + +以下所有程式碼 + +``` +import React, { Component } from 'react'; +import { + AppRegistry, + StyleSheet, + Text, + View +} from 'react-native'; + +class app3 extends Component { + render() { + return ( + + + + {/*左邊(由左而右)*/} + 左邊 + + + {/*中間這一塊(由左而右)*/} + + {/*中間裡面包含上面一塊(由上而下)*/} + 中上 + + + {/*中間裡面包含下面一塊(由上而下)*/} + 中下 + + + + + {/*右邊(由左而右)*/} + 右邊 + + + ); + } +} + +const styles = StyleSheet.create({ + container: { + flex: 1, + flexDirection:'row', //這裡設定由左而右排,若未設定預設是從上而下 + justifyContent: 'center', + alignItems: 'stretch', + backgroundColor: '#F5FCFF', + }, + welcome: { + fontSize: 20, + textAlign: 'center', + margin: 10, + }, + instructions: { + textAlign: 'center', + color: '#333333', + marginBottom: 5, + }, +}); + +AppRegistry.registerComponent('app3', () => app3); +```