react是R系技術棧中最基礎同時也是最核心的一環,2年不到獲取了62.5k star(截止到目前),足可見其給力程度。下面對一些react平常開發中的注意事項進行羅列。html
react主要思想是構建可複用組件來構建用戶界面。在react裏面一切皆組件。每一個組件裏面都是有本身的生命週期,這個生命週期規定了組件的狀態和方法,分別在哪一個階段執行。下面附上一張React的生命週期圖: react
組件第一階段:初始化、渲染以及裝載完成; git
組件第二階段:組件運行時候的狀態 ①:狀態變化引起組件的更新和從新渲染到更新完成 github
②:父組件屬性變化引起組件的更新(是常見的組件之間傳遞數據和同步狀態的手段):好比父組件登陸了,子組件也需變成登陸狀態ide
組件第三階段:卸載組件函數
const names = ['Alice', 'Emily', 'Kate']; ReactDOM.render( <div> { names.map((name) => { return <div>Hello, {name}!</div>
}) } </div>,
document.getElementById('example') );
JSX 的基本語法規則:遇到 HTML 標籤(以 <
開頭),就用 HTML 規則解析;遇到代碼塊(以 {
開頭),就用 JavaScript 規則解析。this
因此給jsx添加註釋只要這樣子:spa
{/* 。。。 */}
子:
var HelloMessage = React.createClass({ render: function() { return <h1>Hello {this.props.name}</h1>;
} }); ---------------------------------------
父: ReactDOM.render( <HelloMessage name="Muyy" />,
document.getElementById('example') );
變量 HelloMessage
就是至關於一個子組件類。經過this.props.name獲取到了Muyy。3d
另外注意code
render
方法,用於輸出組件。HelloMessage
不能寫成helloMessage
class
屬性須要寫成 className
,for
屬性須要寫成 htmlFor
,這是由於 class
和 for
是 JavaScript 的保留字其實很簡單,歸納起來就是:react中state改變了,組件纔會update。父組件寫好state和處理該state的函數,同時將函數名經過props屬性值的形式傳入子,子調用父的函數,同時引發state變化。
例子1.這裏以下圖,用戶郵箱爲父,綠色框爲子。 父組件爲用戶輸入的郵箱設好state,即「{email: ''}」,同時寫好處理state的函數,即「handleEmail」,這兩個名稱隨意起;再將函數以props的形式傳到子組件,子組件只需在事件發生時,調用父組件傳過來的函數便可。
1 //子組件 2 var Child = React.createClass({ 3 render: function(){ 4 return ( 5 <div> 6 請輸入郵箱:<input onChange={this.props.handleEmail}/> 7 </div> 8 ) 9 } 10 }); 11 //父組件,此處經過event.target.value獲取子組件的值 12 var Parent = React.createClass({ 13 getInitialState: function(){ 14 return { 15 email: '' 16 } 17 }, 18 handleEmail: function(event){ 19 this.setState({email: event.target.value}); 20 }, 21 render: function(){ 22 return ( 23 <div> 24 <div>用戶郵箱:{this.state.email}</div> 25 <Child name="email" handleEmail={this.handleEmail.bind(this)}/> 26 </div> 27 ) 28 } 29 }); 30 React.render( 31 <Parent />, 32 document.getElementById('test') 33 );
例子2.有時候每每須要對數據作處理,再傳給父組件,好比過濾或者自動補全等等,下面的例子對用戶輸入的郵箱作簡單驗證,自動過濾非數字、字母和"@."之外的字符。
1 //子組件,handleVal函數處理用戶輸入的字符,再傳給父組件的handelEmail函數 2 var Child = React.createClass({ 3 handleVal: function() { 4 var val = this.refs.emailDom.value; 5 val = val.replace(/[^0-9|a-z|\@|\.]/ig,""); 6 this.props.handleEmail(val); 7 }, 8 render: function(){ 9 return ( 10 <div> 11 請輸入郵箱:<input ref="emailDom" onChange={this.handleVal}/> 12 </div> 13 ) 14 } 15 }); 16 //父組件,經過handleEmail接受到的參數,即子組件的值 17 var Parent = React.createClass({ 18 getInitialState: function(){ 19 return { 20 email: '' 21 } 22 }, 23 handleEmail: function(val){ 24 this.setState({email: val}); 25 }, 26 render: function(){ 27 return ( 28 <div> 29 <div>用戶郵箱:{this.state.email}</div> 30 <Child name="email" handleEmail={this.handleEmail.bind(this)}/> 31 </div> 32 ) 33 } 34 }); 35 React.render( 36 <Parent />, 37 document.getElementById('test') 38 );
例子3.若是還存在孫子組件的狀況呢?以下圖,黑框爲父,綠框爲子,紅框爲孫,要求子孫的數據都傳給爺爺。原理同樣的,只是父要將爺爺對孫子的處理函數直接傳下去。
1 //孫子,將下拉選項的值傳給爺爺 2 var Grandson = React.createClass({ 3 render: function(){ 4 return ( 5 <div>性別: 6 <select onChange={this.props.handleSelect}> 7 <option value="男">男</option> 8 <option value="女">女</option> 9 </select> 10 </div> 11 ) 12 } 13 }); 14 //子,將用戶輸入的姓名傳給爹 15 //對於孫子的處理函數,父只需用props傳下去便可 16 var Child = React.createClass({ 17 render: function(){ 18 return ( 19 <div> 20 姓名:<input onChange={this.props.handleVal}/> 21 <Grandson handleSelect={this.props.handleSelect}/> 22 </div> 23 ) 24 } 25 }); 26 //父組件,準備了兩個state,username和sex用來接收子孫傳過來的值,對應兩個函數handleVal和handleSelect 27 var Parent = React.createClass({ 28 getInitialState: function(){ 29 return { 30 username: '', 31 sex: '' 32 } 33 }, 34 handleVal: function(event){ 35 this.setState({username: event.target.value}); 36 }, 37 handleSelect: function(event) { 38 this.setState({sex: event.target.value}); 39 }, 40 render: function(){ 41 return ( 42 <div> 43 <div>用戶姓名:{this.state.username}</div> 44 <div>用戶性別:{this.state.sex}</div> 45 <Child handleVal={this.handleVal.bind(this)} handleSelect={this.handleSelect.bind(this)}/> 46 </div> 47 ) 48 } 49 }); 50 React.render( 51 <Parent />, 52 document.getElementById('test') 53 );
getDefaultProps
方法能夠用來設置組件屬性的默認值
var MyTitle = React.createClass({ getDefaultProps : function () { return { title : 'Hello World' }; }, render: function() { return <h1> {this.props.title} </h1>; } }); ReactDOM.render( <MyTitle />, document.body );
getInitialState 方法能夠用來設置初始狀態
getInitialState: function() { return {liked: false}; },
從組件獲取真實 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> ); } }); ReactDOM.render( <MyComponent />, document.getElementById('example') );
上面代碼中,組件 MyComponent
的子節點有一個文本輸入框,用於獲取用戶的輸入。這時就必須獲取真實的 DOM 節點,虛擬 DOM 是拿不到用戶輸入的。爲了作到這一點,文本輸入框必須有一個 ref
屬性,而後 this.refs.[refName]
就會返回這個真實的 DOM 節點。
須要注意的是,因爲 this.refs.[refName]
屬性獲取的是真實 DOM ,因此必須等到虛擬 DOM 插入文檔之後,才能使用這個屬性,不然會報錯。上面代碼中,經過爲組件指定 Click
事件的回調函數,確保了只有等到真實 DOM 發生 Click
事件以後,纔會讀取 this.refs.[refName]
屬性。
React 組件支持不少事件,除了 Click
事件之外,還有 KeyDown
、Copy
、Scroll
等,完整的事件清單請查看官方文檔。
父組件調用子組件的state、function,除了上面介紹的方法以外,也能夠經過ref屬性實現。推薦使用這種方式進行子組件向父組件的傳遞。舉個簡單的示範:
export default class 父組件a extends React.Component { constructor(props) { super(props) } render() { return ( <子組件b ref={r => this.bbbb =r} // bbbb自定義名字 /> ) } }
通過這樣處理後後,如今父組件a中能夠經過this.bbbb.state.xxx獲取子組件的xxx狀態,也能夠經過this.bbbb.xxx獲取子組件的xxx方法。