@(React學習)javascript
React 容許將代碼封裝成組件(component),而後像插入普通 HTML 標籤同樣,在網頁中插入這個組件。html
組件類只能包含一個頂層標籤,不然會報錯。java
var HelloXiaowang = React.createClass({ render: function() { return <h1>Hello {this.props.name}</h1>; } }); ReactDOM.render( <HelloXiaowang name="junyan" />, document.getElementById('shuaige') );
上面代碼中,變量 HelloXiaowang 就是一個組件類。模板插入 HelloXiaowang /> 時,會自動生成 HelloXiaowang 的一個實例(下文的"組件"都指組件類的實例)。react
全部組件類都必須有本身的render方法,用於輸出組件
ReactElement render ( )git
當調用的時候,會檢測 this.props 和 this.state,返回一個單子級組件。該子級組件能夠是虛擬的本地 DOM 組件(好比 div /> 或者 React.DOM.div()),也能夠是自定義的複合組件。github
var HelloXiaowang = React.createClass({ render: function() { return <h1>Hello {this.props.name}</h1>; } });
render ( ) 函數應該是純粹的,也就是說該函數不修改組件 s瀏覽器
tate,每次調用都返回相同的結果,不讀寫 DOM 信息,也不和瀏覽器交互(例如經過使用 setTimeout)。若是須要和瀏覽器交互,在 componentDidMount() 中或者其它生命週期方法中作這件事。保持 render() 純粹,可使服務器端渲染更加切實可行,也使組件更容易被理解。服務器
組件本質上是狀態機,輸入肯定,輸出必定肯定app
狀態機本質上是狀態與轉移的結合。當狀態發生轉換時會觸發不一樣的鉤子函數,從而讓開發者有機會作出相應。
組件的聲明週期分紅三個狀態:函數
Mounting:初始化階段(已插入真實 DOM)
Updating:運行中階段(正在被從新渲染)
Unmounting:銷燬階段(已移出真實 DOM)
類建立完成以後,就能夠進行實例化。
getDefaultProps: 只調用一次,實例之間共享引用
getInitialState: 初始化每一個實例特有的狀態
componentWillMount: render
以前最後一次修改狀態的機會。若是在這個方法內調用setState
,render()
將會感知到更新後的state
,將會執行僅一次,儘管state
改變了。
render: 只能訪問this.props和this.state,只有一個頂層組件,不容許修改狀態和DOM輸出
componentDidMount: 成功render並渲染完成真實DOM以後觸發,能夠修改DOM
當組件在客戶端被實例化,第一次被建立時,如下方法依次被調用:
getDefaultProps
getInitialState
componentWillMount
render
componentDidMount
當組件在服務端被實例化,首次被建立時,如下方法依次被調用:
getDefaultProps
getInitialState
componentWillMount
render
componentDidMount 不會在服務端被渲染的過程當中調用。
getDefaultProps方法不是在組件建立的時候調用,而是在createClass時調用。
var count = 0; var HelloWorld = React.createClass({ getDefaultProps:function(){ return {name:"dada"}; }, getInitialState:function(){ return { myCount:count++, ready:false }; }, componentWillMount:function(){ this.setState({ready:true}); }, render:function(){ return <p>Hello,{this.props.name?this.props.name:"World"} <br/>{''+this.props.ready}{this.state.myCount}</p>; }, componentDidMount:function(){ $(ReactDOM.findDOMNode(this)).append("bianke"); } }); ReactDOM.render(<HelloWorld/>,document.getElementById('shuage'))
阮老師例子:
var Hello = React.createClass({ getInitialState: function () { return { opacity: 1.0 }; }, componentDidMount: function () { this.timer = setInterval(function () { var opacity = this.state.opacity; opacity -= .05; if (opacity < 0.1) { opacity = 1.0; } this.setState({ opacity: opacity }); }.bind(this), 100); }, render: function () { return ( <div style={{opacity: this.state.opacity}}> Hello {this.props.name} </div> ); } }); ReactDOM.render( <Hello name="world"/>, document.body );
上面代碼在hello組件加載之後,經過 componentDidMount 方法設置一個定時器,每隔100毫秒,就從新設置組件的透明度,從而引起從新渲染。
另外組件的style屬性的設置方式要寫成
style={{opacity: this.state.opacity}}
React.findDOMNode()
若是這個組件已經被初始化到DOM中,這個方法返回相應的原生瀏覽器的DOM元素。這個方法用於讀取這個DOM的值,例如表單的值與DOM的方法。在多數狀況下附加一個ref
屬性與DOM節點上,用來避免使用findDOMNode
。當render
返回null或false時,findDOMNode
也返回null。
注意:
findDOMNode
是一個用來訪問底層DOM節點的出口。在大多數狀況下,是不鼓勵用出口,由於他穿過了組件的層
findDOMNode
僅僅是在初始化階段的組件起做用(由於組件已經存在於DOM結構中)。若是你嘗試在還沒有在初始化階段的組件中調用這個方法(就像render()函數中組件還沒有建立就調用這個方法)會拋出異常。
findDOMNode
不能用於沒有狀態的組件中。
getDOMNode
已過期,不建議使用。
此時組件已經渲染好而且用戶能夠與它進行交互,好比鼠標點擊,手指點按,或者其它的一些事件,致使應用狀態的改變
componentWillReceiveProps:父組件修改屬性觸發,能夠修改新屬性、修改狀態。它是在組件發生改變以前觸發
shouldComponentUpdate:返回false會阻止render調用
componentWillUpdate:不能修改屬性與狀態
render: 只能訪問this.props和this.state,只有一個頂層組件,不容許修改狀態和DOM輸出
componentDidUpdate:能夠修改DOM
在組件接收到新的 props 的時候調用。在初始化渲染的時候,該方法不會調用。
用此函數能夠做爲 react 在 prop 傳入以後, render()
渲染以前更新 state 的機會。老的 props 能夠經過this.props
獲取到。在該函數調用用this.setState()
將不會引發第二次渲染。
componentWillReceiveProps: function(nextProps) { this.setState({ likesIncreasing: nextProps.likeCount > this.props.likeCount }); }
對於 state,沒有類似的方法:
componentWillReceiveState
。將要傳進來的 prop 可能會引發 state 改變,反之則否則。若是須要在 state 改變的時候執行一些操做,請使componentWillUpdate
。
在接收到新的 props 或者 state,將要渲染以前調用。該方法在初始化渲染的時候不會調用,在使用 forceUpdate 方法的時候也不會。
若是肯定新的 props 和 state 不會致使組件更新,則此處應該 返回 false。
shouldComponentUpdate: function(nextProps, nextState) { return nextProps.id !== this.props.id; }
若是shouldComponentUpdate
返回 false,則render()
將不會執行,直到下一次 state 改變。
若是性能是個瓶頸,尤爲是有幾十個甚至上百個組件的時候,使用
shouldComponentUpdate
能夠提高應用的性能。
默認狀況下shouldComponentUpdate
總會返回 true,在 state 改變的時候避免細微的 bug,可是若是老是當心地把 state 當作不可變的,在render()
中只從 props 和 state 讀取值,此時你能夠覆蓋shouldComponentUpdate
方法,實現新老 props 和 state 的比對邏輯。
在接收到新的 props 或者 state 以前馬上調用。在初始化渲染的時候該方法不會被調用。使用該方法作一些更新以前的準備工做。
你不能在此方法中使用
this.setState()
。若是須要更新 state 來響應某個 prop 的改變,請使用componentWillReceiveProps
。
在組件的更新已經同步到 DOM 中以後馬上被調用。該方法不會在初始化渲染的時候調用。使用該方法能夠在組件更新以後操做 DOM 元素。
每次修改 state,都會從新渲染組件,實例化後經過 state 更新組件,會依次調用下列方法:
shouldComponentUpdate
componentWillUpdate
render
componentDidUpdate
可是不要直接修改 this.state,要經過 this.setState 方法來修改。
正確用法
var HelloXianrou = React.createClass({ componentWillReceiveProps:function(newProps){ console.log(newProps); }, render:function () { console.log(4); return <p>Hello {this.props.name||"World"}</p> }, componentDidUpdate:function () { $(ReactD.findDOMNode(this)).append("<p>大大是大帥哥</p>") } }); var HelloDada = React.createClass({ getInitialState:function () { return {name:''}; }, handleChange:function (e) { this.setState({name:e.target.value}); }, render:function () { return <div> <HelloXianrou name={this.state.name}></HelloXianrou> <br/> <input type="text" onChange={this.handleChange} /> </div> } }); ReactDOM.render(<HelloDada></HelloDada>,document.getElementById('reactDemo'))
componentWillUnmount
:在刪除組件以前進行清理操做,好比計時器和事件監聽器。或者清除在 componentDidMount 中建立的 DOM 元素。
移除一個已經初始化DOM過的React組件,清理它的操做和狀態。若是這個組件中沒有初始化過的組件,這個方法沒有任何做用。若是這個組件被銷燬則返回true,反之返回false
var HelloXianrou = React.createClass({ render:function () { console.log(4); return <p>Hello {this.props.name||"World"}</p> }, componentWillUnmount:function () { console.log("Booooooooooom!!") } }); var HelloDada = React.createClass({ getInitialState:function () { return {name:''}; }, handleChange:function (e) { /* if (e.target.value == "123") { React.unmountComponentAtNode(document.getElementById('reactDemo')[0]); return; } */ this.setState({name:e.target.value}); }, render:function () { /* if(this.state.name == "123"){ return <p>123</p> } */ return <div> <HelloXianrou name={this.state.name}></HelloXianrou> <br/> <input type="text" onChange={this.handleChange} /> </div> } }); ReactDOM.render(<HelloDada></HelloDada>,document.getElementById('reactDemo'))
本文主要介紹了組件的生命週期。許多方法在組件生命週期中某個肯定的時間點執行。