1.使用虛擬DOM做爲其不一樣的實現。同時能夠由服務器node.js渲染,從而不須要太重的瀏覽器DOM支持。javascript
1)獲取屬性的值用的是this.props.屬性名css
2)建立的組件名稱首字母必須大寫。html
3)爲元素添加css的class時,要用className。java
4)組件的style屬性的設置方式也值得注意,要寫成style={{width: this.state.witdh}}。這是由於 React 組件樣式是一個對象,因此第一重大括號表示這是 JavaScript 語法,第二重大括號表示樣式對象。node
5.組件狀態react
react將組件看作一個狀態機,一旦組件的狀態發生改變,react就會觸發從新渲染UI(自動調用this.render)。經過this.state.XX來定義和設置用戶自定義的狀態。而getInitialState函數則是在組件初始化時執行,返回null或一個對象。例:jquery
var InputState = React.createClass({git
getInitialState:function(){程序員
return {enable:false};github
},
handleClick:function(event){
this.setState({enable:!this.state.enable});
},
render:function(){
return (
<p>
<input type="text" disabled={this.state.enable} />
<button onClick={this.handleClick}>Change State</button>
</p>
);
}
});
這裏值得注意的幾點以下:
1)getInitialState函數必須有返回值,能夠是NULL或者一個對象。
2)訪問state的方法是this.state.屬性名。
3)變量用{}包裹,不須要再加雙引號。
6.react組件的生命週期有3個
Mounting:已插入真實 DOM
Updating:正在被從新渲染
Unmounting:已移出真實 DOM
每一個狀態都有兩種處理函數,will在進入狀態前執行,did在進入以後執行,共五種處理函數:
componentWillMount()
componentDidMount()
componentWillUpdate(object nextProps, object nextState)
componentDidUpdate(object prevProps, object prevState)
componentWillUnmount()
此外,react還提供2種特殊狀態的處理函數:
componentWillReceiveProps(object nextProps):已加載組件收到新的參數時調用
shouldComponentUpdate(object nextProps, object nextState):組件判斷是否從新渲染時調用
7.this.props 對象的屬性與組件的屬性一一對應,可是有一個例外,就是 this.props.children 屬性。它表示組件的全部子節點
這裏須要注意, this.props.children 的值有三種可能:若是當前組件沒有子節點,它就是 undefined ;若是有一個子節點,數據類型是 object ;若是有多個子節點,數據類型就是 array 。因此,處理 this.props.children 的時候要當心。
React 提供一個工具方法 React.Children 來處理 this.props.children 。咱們能夠用 React.Children.map 來遍歷子節點,而不用擔憂 this.props.children 的數據類型是 undefined 仍是 object。更多的 React.Children 的方法,請參考
https://facebook.github.io/react/docs/top-level-api.html#react.children
8.組件的屬性能夠接受任意值,字符串、對象、函數等等均可以。有時,咱們須要一種機制,驗證別人使用組件時,提供的參數是否符合要求。
組件類的PropTypes屬性,就是用來驗證組件實例的屬性是否符合要求
var MyTitle = React.createClass({ propTypes:{ title: React.PropTypes.string.isRequired,}, render:function(){return<h1>{this.props.title}</h1>;}});
這樣,就規定了MyTitle的title屬性是必須的,且類型爲字符串。若是不符合要求,控制檯就會報錯。
更多的PropTypes設置,能夠查看官方文檔。
此外,getDefaultProps 方法能夠用來設置組件屬性的默認值。
getDefaultProps :function(){return{ title :'Hello World'};},
9.組件並非真實的DOM節點,而是存在於內存之中的一種數據結構,叫作虛擬 DOM 。
可是,有時須要從組件獲取真實 DOM 的節點,這時就要用到 ref 屬性
var MyComponent = React.createClass({ handleClick:function(){ this.refs.myTextInput.focus();}, render:function(){return(<div><input type="text" ref="myTextInput"/><input type="button" value="Focus the text input" onClick={this.handleClick}/></div>);}});
文本輸入框有一個 ref 屬性,而後 this.refs.[refName] 就會返回這個真實的 DOM 節點。須要注意的是,因爲 this.refs.[refName] 屬性獲取的是真實 DOM ,因此必須等到虛擬 DOM 插入文檔之後,才能使用這個屬性。
10.組件的構造規則跟函數或者對象的構造規則有殊途同歸之妙,最大的共同點就是單一功能原則,即一個組件應該儘可能只作一件事情,若是它的功能逐漸擴大就須要被拆分爲更小的子組件。
13.經常使用的通知React 數據變化的方法是調用 setState(data, callback) 。這個方法會合並(merge) data 到 this.state,並從新渲染組件。渲染完成後,調用可選的callback 回調。大部分狀況下不須要提供 callback ,由於 React 會負責把界面更新到最新狀態。嘗試把儘量多的組件無狀態化。 這樣作能隔離 state,把它放到最合理的地方,也能減小冗餘並,同時易於解釋程序運做過程。經常使用的模式是建立多個只負責渲染數據的無狀態(stateless)組件,在它們的上層建立一個有狀態(stateful)組件並把它的狀態經過 props 傳給子級。這個有狀態的組件封裝了全部用戶的交互邏輯,而這些無狀態組件則負責聲明式地渲染數據。
15.若是子級要在多個渲染階段保持本身的特徵和狀態,在這種狀況下,你能夠經過給子級設置唯一標識的 key 來區分。當 React 校訂帶有 key 的子級時,它會確保它們被從新排序(而不是破壞)或者刪除(而不是重用)。 務必把 key 添加到子級數組裏組件自己上,而不是每一個子級內部最外層 HTML 上。
時候必定確保你清楚到底作了什麼,而且只在遇到明顯性能問題的時候才使用它。不要低估 JavaScript 的速
度,DOM 操做一般纔是慢的緣由。
17. 傳遞Props的技巧,若是想把傳入組件的所有props複製到對應的HTML元素上,<a {...this.props}>便可。有時候不須要傳遞全部屬性,可以使用 var { checked, ...other } = this.props; 再調用other即表明除了checked之外全部的props,而checked就是this,props.checked,能夠直接使用,多個屬性能夠用逗號隔開。若是不使用 JSX,可使用一些庫來實現相同效果。Underscore 提供 _.omit 來過濾屬性, _.extend 複製屬性到新的對象。P60
var FancyCheckbox = React.createClass(
render: function() {
var checked = this.props.checked;
var other = _.omit(this.props, 'checked');
var fancyClass = checked ? 'FancyChecked' : 'FancyUnchecked';
return (
React.DOM.div(_.extend({}, other, { className: fancyClass }))
);
}
});
• 不可變的:一旦建立,集合不能在另外一個時間點改變。
• 持久性:新的集合能夠由從早先的集合和突變結合建立。在建立新的集合後,原來集合仍然有效。
• 結構共享:使用新的集合建立爲與對原始集合大體相同的結構,減小了拷貝的最低限度,以實現空間效率和可接受的性能。若是新的集合等於原始的集合,則一般會返回原來的集合。
不變性使得跟蹤更改方便;而變化將老是產生在新的對象,因此咱們只須要檢查的已經改變參考對象。
即原始的對象是不變的,每當對原始數據進行改變,會建立一個新的對象。
例:
var SomeRecord = Immutable.Record({ foo: null });
var x = new SomeRecord({ foo: 'bar' });
var y = x.set('foo', 'baz');
x === y; // false
26. React API
(1)React.createClass 再也不贅述。
(2)React.createElement:
ReactElement createElement(
string/ReactClass type,
[object props],
[children ...]
)
建立並返回一個新的指定類型的 ReactElement。type 參數能夠是一個 html 標籤名字字符串(例如,「div」,「span」,等等),或者是 ReactClass (經過 React.createClass 建立的)。
factoryFunction createFactory(
string/ReactClass type
)
返回一個生成指定類型 ReactElements 的函數。好比 React.createElement,type 參數能夠是一個 html 標籤名字字符串(例如,「div」,「span」,等等),或者是 ReactClass 。
從 DOM 中移除已經掛載的 React 組件,清除相應的事件處理器和 state。若是在 container 內沒有組件掛 載,這個函數將什麼都不作。若是組件成功移除,則返回 true ;若是沒有組件被移除,則返回 false 。
把組件渲染成原始的 HTML 字符串。該方法應該僅在服務器端使用。React 將會返回一個 HTML 字符串。你能夠在服務器端用此方法生成 HTML,而後將這些標記發送給客戶端,這樣能夠得到更快的頁面加載速度,而且有利於搜索引擎抓取頁面,方便作 SEO。
(6) string renderToStaticMarkup(ReactElement element)
和 renderToString 相似,除了不建立額外的 DOM 屬性,例如 data-react-id ,由於這些屬性僅在 React 內部使用。若是你想用 React 作一個簡單的靜態頁面生成器,這是頗有用的,由於丟掉額外的屬性可以節省不少字節。
(7)React.isValidElement
boolean isValidElement(* object)判斷對象是不是一個 ReactElement。
(8)initializeTouchEvents(boolean shouldUseTouch)
配置 React 的事件系統,使 React 能處理移動設備的觸摸( touch )事件。
(9)React.ChildrenReact.Children
React.Children 爲處理 this.props.children 這個封閉的數據結構提供了有用的工具。
詳情見P82,有.map 、.forEach、.count、.only等用法。
27.ReactComponent
React 組件實例在渲染的時候建立。這些實例在接下來的渲染中被重複使用,能夠在組件方法中經過 this 訪問。惟一一種在 React 以外獲取 React 組件實例句柄的方式就是保存 React.render 的返回值。在其它組件內,可使用 refs 獲得相同的結果。
(1)setState(object nextState[, function callback]))
合併 nextState 和當前 state。這是在事件處理函數中和請求回調函數中觸發 UI 更新的主要方法。另外,也支持可選的回調函數,該函數在 setState 執行完畢而且組件從新渲染完成以後調用。
注:setState() 不會馬上改變 this.state ,而是建立一個即將處理的 state 轉變。在調用該方法以後獲取 this.state 的值可能會獲得現有的值,而不是最新設置的值。
(3)forceUpdate([function callback])
若是 render() 方法從 this.props 或者 this.state 以外的地方讀取數據,你須要經過調用 forceUpdate() 告訴 React 何時須要再次運行 render()。若是直接改變了 this.state ,也須要調用 forceUpdate()。
注:應該儘可能避免使用forceUpdate的狀況。
(4)bool isMounted()
若是組件渲染到了 DOM 中, isMounted() 返回 true。可使用該方法保證 setState() 和 forceUpdate() 在異步場景下的調用不會出錯。
(5)
28.render() 函數應該是純粹的,也就是說該函數不修改組件 state,每次調用都返回相同的結果,不讀寫 DOM 信息,也不和瀏覽器交互(例如經過使用 setTimeout )。若是須要和瀏覽器交互,在 componentDidMount()中或者其它生命週期方法中作這件事。保持 render() 純粹,可使服務器端渲染更加切實可行,也使組件更容易被理解。
29.object statics
statics 對象容許你定義靜態的方法,這些靜態的方法能夠在組件類上調用。
30. React 也提供了一些 DOM 裏面不存在的屬性。
• key :可選的惟一的標識器。當組件在 渲染 過程當中被各類打亂的時候,因爲差別檢測邏輯,可能會被銷燬後從新建立。給組件綁定一個 key,能夠持續確保組件還存在 DOM 中。
• ref:參考這裏 (頁 0)。
• dangerouslySetInnerHTML :提供插入純 HTML 字符串的功能,主要爲了能和生成 DOM 字符串的庫整合。
31.React的渲染策略
(1)若先後兩個節點元素或者組件的類型不一樣,React會直接把他們當作不一樣的子樹,甚至不會嘗試計算出該渲染什麼,直接從DOM中移除以前的節點,而後插入新的節點。
(2)比較兩個DOM節點的時候,查看二者的屬性,而後找出變化的屬性。
(3)對於自定義組件,React決定2個自定義組件是相同的,利用新組件上的全部屬性,而後再以前的組件實例上調用componetWill(Did)ReceiveProps()。如今,以前的組件的render(0被調用,而後差別算法從新比較新的狀態和上一次的狀態。
(4)爲了完成子級更新,React同時遍歷兩個子級列表,當發現差別的時候,就產生一次DOM修改。
在開始處插入元素比較麻煩。React 發現兩個節點都是 span,所以直接修改已有 span 的文本內容,而後在後面插入一個新的 span 節點。
renderA:<div><span>first</span></div>
renderB:<div><span>secon</span><span>first</span></div>爲了解決這個問題,引入了一個可選的屬性keys。若是指定了一個鍵值,React 就可以檢測出節點插入、移除和替換,而且藉助哈希表使節點移動複雜度爲O(n)。
注:鍵值只須要在兄弟節點中惟一,而不是全局惟一。
var divStyle = {
color: 'white',
backgroundImage: 'url(' + imgUrl + ')',
WebkitTransition: 'all', // 注意這裏的首字母'W'是大寫
msTransition: 'all' // 'ms'是惟一一個首字母須要小寫的瀏覽器前綴
};
React.render(Hello World!, mountNode);
33.一般,一個組件的子代(this.props.children)是一個組件的數組,即爲數組類型,可是當只有一個子代的時候,this.props.children是一個單獨的組件,而不是數組形式,這樣就減小了數組的佔用。
34.getInitialState裏的props是一個反模式。詳情見P118。
35.給DOM元素綁定React未提供的事件,好比想共用react和jquery的時候,在componentDidMount中 調用
component.addEventListener('xxx', this.handleResize) 綁定事件,在componentWillUnmount中removeEventListener()取消綁定。詳情見P120
當執行同步請求的響應時,在更新 state 前, 必定要先經過 this.isMounted() 來檢測組件的狀態是否仍是 mou
nted。