接着上一次的講,如果沒有看過上一篇文章的小伙伴可以先看一下http://www.cnblogs.com/sakurayeah/p/5807821.html
五、React事件
可以先看一下官網講解的內容
案例6:以點擊事件為例
<!DOCTYPE html> <html> <head> <title>react入門</title> <meta charset="utf-8"> <script src="https://npmcdn.com/react@15.3.1/dist/react.min.js"></script> <script src="https://npmcdn.com/react-dom@15.3.1/dist/react-dom.min.js"></script> <script src="https://npmcdn.com/babel-core@5.8.38/browser.min.js"></script> </head> <body> <div id="example"></div> <script type="text/babel"> var fn3 = function(){/*方法3*/ console.log(333) } var Test = React.createClass({ fn1:function(){/*方法1*/ console.log(111) },/*注意這里是逗號哦*/ render:function(){ var fn2 = function(){/*方法2*/ console.log(222) }; return ( <div> <button onClick={this.fn1}>方法1</button> <button onClick={fn2}>方法2</button> <button onClick={fn3}>方法3</button> <button onClick={this.fns.fn4}>方法4</button> </div> ) } }); Test.prototype.fns = {/*方法4,原型鏈*/ fn4:function(){ console.log(444) }, } ReactDOM.render( <Test />, document.getElementById('example') ) </script> </body> </html>
上面列舉了四種方法,效果圖如下
react本身定義了一套事件機制遵守W3C標准,規范規定事件名稱前面小寫,后面關鍵字首字母大寫。
例如(箭頭前為js寫法,箭頭后為react的寫法)
onclick --> onClick。
onchange --> onChange
onfocus --> onFocus
onblur --> onBlur
onmousemove --> onMouseMove
...... (有很多,可以參考官網看一下)
六、this.props.children
this.props 對象的屬性與組件的屬性一一對應,但是有一個例外,就是 this.props.children 屬性。它表示組件的所有子節點。
案例7:
<!DOCTYPE html> <html> <head> <title>react入門</title> <meta charset="utf-8"> <script src="https://npmcdn.com/react@15.3.1/dist/react.min.js"></script> <script src="https://npmcdn.com/react-dom@15.3.1/dist/react-dom.min.js"></script> <script src="https://npmcdn.com/babel-core@5.8.38/browser.min.js"></script> <style type="text/css"> .tab{background:yellow;} </style> </head> <body> <div id="example"></div> <script type="text/babel"> var Test = React.createClass({ render:function(){ return ( <div> {this.props.children} </div> ) } }); var Box = React.createClass({ render:function(){ return( <Test> <span>序號1,</span> <span>序號2,</span> <span>序號3,</span> </Test> ) } }); ReactDOM.render( <Box />, document.getElementById('example') ) </script> </body> </html>
效果如下
上圖所示,紅框勾起來的部分,div里面包含的所有標簽都是 Test 這個組件里面的。
如果把Test這個組件刪除掉,如下圖所示,如果你將下面紅框框起來的代碼刪除
就會發現報錯,如下圖所示
分析如下
Box組件里<Test>標簽里的內容,通過this.props.children,相當於放到了Test組件里去了,然后再將Test組件放在Box組件里,最后將Box組件渲染在頁面上,也就相當於如下
var Test = React.createClass({ render:function(){ return ( <div> <span>序號1,</span> <span>序號2,</span> <span>序號3,</span> </div> ) } }); var Box = React.createClass({ render:function(){ return( <Test /> ) } }); ReactDOM.render( <Box />, document.getElementById('example') )
效果如下
案例8:
<!DOCTYPE html> <html> <head> <title>react入門</title> <meta charset="utf-8"> <script src="https://npmcdn.com/react@15.3.1/dist/react.min.js"></script> <script src="https://npmcdn.com/react-dom@15.3.1/dist/react-dom.min.js"></script> <script src="https://npmcdn.com/babel-core@5.8.38/browser.min.js"></script> <style type="text/css"> .tab{background:yellow;} </style> </head> <body> <div id="example"></div> <script type="text/babel"> var Test = React.createClass({ render:function(){ return ( <div> { React.Children.map(this.props.children, function(child,index) { return <p>序號{index}:{child}</p>; }) } </div> ) } }); var Box = React.createClass({ render:function(){ return( <Test> <span>電影</span> <span>電視劇</span> <span>綜藝</span> </Test> ) } }); ReactDOM.render( <Box />, document.getElementById('example') ) </script> </body> </html>
效果如下
先來說一下上面這個例子中涉及到的map循環
React 提供一個工具方法 React.Children 來處理 this.props.children 。我們可以用 React.Children.map 來遍歷子節點,而不用擔心 this.props.children 的數據類型是 undefined 或者是 object 還是 array。
把map循環:和for循環對比一下來解釋
先寫一個for循環
var arr = [1,2,3,4]; for(var i=0;i<arr.length;i++){ console.log(arr[i]) }
這里有一個點要注意一下,Test組件里面的子節點的個數(上面的例子中Text組件的有三個span子節點)會影響this.props.children的值:
- 如果Test組件沒有子節點,this.props.children為undefined
- 如果Test組件有一個子節點,this.props.children為object
- 如果Test組件有多個子節點,this.props.children為array
上面一個例子也就相當於,將Box組件里Test標簽里的三個子節點,通過this.props.children放到了Test組件里去,這時候也就相當於Test組件里有一個數組了,數組里面是對應的三個span節點,通過map遍歷,將span標簽放入到p標簽中去,然后再將Test組件放到Box組件里,最終將Box組件渲染到頁面上。如下所示
<body> <div id="example"></div> <script type="text/babel"> var Test = React.createClass({ render:function(){ var arr = [<span>電影</span>, <span>電視劇</span>, <span>綜藝</span>]; var temp = []; for(var i=0;i<arr.length;i++){ temp.push(<p>序號{i}:{arr[i]}</p>); } return ( <div> {temp} </div> ) } }); var Box = React.createClass({ render:function(){ return( <Test /> ) } }); ReactDOM.render( <Box />, document.getElementById('example') ) </script> </body>
效果如下
除了React.Children.map,關於React.Children的更多的方法,可以看官網
七、傳遞props
React 里有一個非常常用的模式就是對組件做一層抽象。組件對外公開一個簡單的屬性(Props)來實現功能,但內部細節可能有非常復雜的實現。
案例9:父-子組件的通信
<!DOCTYPE html> <html> <head> <title>react入門</title> <meta charset="utf-8"> <script src="https://npmcdn.com/react@15.3.1/dist/react.min.js"></script> <script src="https://npmcdn.com/react-dom@15.3.1/dist/react-dom.min.js"></script> <script src="https://npmcdn.com/babel-core@5.8.38/browser.min.js"></script> <style type="text/css"> .tab{background:yellow;} </style> </head> <body> <div id="example"></div> <script type="text/babel"> var Parent = React.createClass({ clicks:function(){ alert('您好') }, render:function(){ return ( <div> <Child user="tom" age="11" fn={this.clicks} /> <Child user="sam" age="13" fn={this.clicks} /> </div> ) } }); var Child = React.createClass({ render:function(){ return ( <div> 年紀:{this.props.user},年齡: {this.props.age}, <button onClick={this.props.fn}>點擊</button><br /> </div> ) } }); ReactDOM.render( <Parent />, document.getElementById('example') ) </script> </body> </html>
效果如下
分析如下
這樣其實也就是相當於實現了組件之間的通信
案例10:
<!DOCTYPE html> <html> <head> <title>react入門</title> <meta charset="utf-8"> <script src="https://npmcdn.com/react@15.3.1/dist/react.min.js"></script> <script src="https://npmcdn.com/react-dom@15.3.1/dist/react-dom.min.js"></script> <script src="https://npmcdn.com/babel-core@5.8.38/browser.min.js"></script> <style type="text/css"> .tab{background:yellow;} </style> </head> <body> <div id="example"></div> <script type="text/babel"> var Parent = React.createClass({ clicks:function(){ alert('您好') }, render:function(){ return ( <div> <Child user="tom" age="11" fn={this.clicks} /> </div> ) } }); var Child = React.createClass({ render:function(){ var { user, age, fn } = this.props; return ( <div> 年紀:{user},年齡: {age}, <button onClick={fn}>點擊</button><br /> </div> ) } }); ReactDOM.render( <Parent />, document.getElementById('example') ) </script> </body> </html>
效果如下
這個例子和上面一個例子相同,只是在子組件Child里面的寫法有一點不同(如下圖紅色框框勾出來的),這里我就不講解,大家看一下知道還可以這么寫就行了
八、關於{...other}
有時把所有屬性都傳下去是不安全或啰嗦的。這時可以使用解構賦值中的剩余屬性特性來把未知屬性批量提取出來。
列出所有要當前使用的屬性,后面跟着 ...other
。
案例11:
<!DOCTYPE html> <html> <head> <title>react入門</title> <meta charset="utf-8"> <script src="https://npmcdn.com/react@15.3.1/dist/react.min.js"></script> <script src="https://npmcdn.com/react-dom@15.3.1/dist/react-dom.min.js"></script> <script src="https://npmcdn.com/babel-core@5.8.38/browser.min.js"></script> <style type="text/css"> .tab{background:yellow;} </style> </head> <body> <div id="example"></div> <script type="text/babel"> var Parent = React.createClass({ clicks:function(){ alert('click') }, enters:function(){ console.log('enter') }, render:function(){ return ( <div> <Child user="tom" age="11" onClick={this.clicks} onMouseEnter={this.enters} /> </div> ) } }); var Child = React.createClass({ render:function(){ var { user, age, ...other } = this.props; return ( <div> 年紀:{user},年齡: {age}, <button {...other}>移動</button><br /> </div> ) } }); ReactDOM.render( <Parent />, document.getElementById('example') ) </script> </body> </html>
效果如下(當鼠標移到按鈕上的時候,打印enter,當點擊按鈕的時候,彈框顯示click)
分析如下
我們現在要傳遞的有user、age、onClick、onMouseEnter(如下圖所示)
當前我們列出來的屬性有user、age(如下圖所示),剩下兩個onClick和onMouseEnter通過 ...other 來傳遞,這樣寫起來也比較簡潔
使用 ...other 能確保把所有 props 傳下去,除了那些已經被使用了的。
九、關於{...this.props}
案例12:
其實也就是 案例11 的另一種寫法(大家知道這么寫就行了,我就不詳細解釋了)
<!DOCTYPE html> <html> <head> <title>react入門</title> <meta charset="utf-8"> <script src="https://npmcdn.com/react@15.3.1/dist/react.min.js"></script> <script src="https://npmcdn.com/react-dom@15.3.1/dist/react-dom.min.js"></script> <script src="https://npmcdn.com/babel-core@5.8.38/browser.min.js"></script> <style type="text/css"> .tab{background:yellow;} </style> </head> <body> <div id="example"></div> <script type="text/babel"> var Parent = React.createClass({ clicks:function(){ alert('click') }, enters:function(){ console.log('enter') }, render:function(){ return ( <div> <Child user="tom" age="11" onClick={this.clicks} onMouseEnter={this.enters} /> </div> ) } }); var Child = React.createClass({ render:function(){ return ( <div> 年紀:{this.props.user},年齡: {this.props.age}, <button {...this.props}>移動</button><br /> </div> ) } }); ReactDOM.render( <Parent />, document.getElementById('example') ) </script> </body> </html>
效果如下
案例13:
<!DOCTYPE html> <html> <head> <title>react入門</title> <meta charset="utf-8"> <script src="https://npmcdn.com/react@15.3.1/dist/react.min.js"></script> <script src="https://npmcdn.com/react-dom@15.3.1/dist/react-dom.min.js"></script> <script src="https://npmcdn.com/babel-core@5.8.38/browser.min.js"></script> <style type="text/css"> .tab{background:yellow;} </style> </head> <body> <div id="example"></div> <script type="text/babel"> var Parent = React.createClass({ render:function(){ return ( <div> <Child checked={true} /> <Child checked={false} /> </div> ) } }); var Child = React.createClass({ render:function(){ var bgOne = { border:'1px solid red' }; var bgTwo = { border:'1px solid blue' }; var { checked } = this.props; var res = checked?'選中':'不選中'; var bg = checked?bgOne:bgTwo; return ( <div style={bg}> <input type="checkbox" checked={checked} /> {res} </div> ) } }); ReactDOM.render( <Parent />, document.getElementById('example') ) </script> </body> </html>
效果如下
父組件中傳遞的信息只有checked是true或者false
在子組件里,我們可以通過這個值來完成多個效果(input是否選中、文字、邊框顏色)
在上面的例子中還有一個問題,父組件中我們傳遞的信息是checked={true},子組件里面input上的屬性checked={checked}。這里希望大家不要混淆了,如下圖所示
checked={checked}還可以寫成checked={this.props.checked}
另外值得一提的是 案例13 里面,我們不可以改變復選框的狀態,這里就涉及到了受阻組件和不受阻組件,這里貼一個教程。