疑问
https://github.com/ruanyf/react-demos/blob/master/demo08/index.html
在如下代码中的 18 行, 需要将本类中的 方法,进行绑定到this,即当前组件,但是render函数就不需要,为什么呢?
this.handleClick = this.handleClick.bind(this)
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="UTF-8" /> 5 <script src="../build/react.development.js"></script> 6 <script src="../build/react-dom.development.js"></script> 7 <script src="../build/babel.min.js"></script> 8 </head> 9 <body> 10 <div id="example"></div> 11 <script type="text/babel"> 12 class LikeButton extends React.Component { 13 constructor(props) { 14 super(props) 15 this.state = { 16 liked: false 17 } 18 this.handleClick = this.handleClick.bind(this) 19 } 20 handleClick(event) { 21 this.setState({ liked: !this.state.liked }); 22 } 23 render() { 24 var text = this.state.liked ? 'like' : 'haven\'t liked'; 25 return ( 26 <p onClick={this.handleClick}> 27 You {text} this. Click to toggle. 28 </p> 29 ); 30 } 31 } 32 33 ReactDOM.render( 34 <LikeButton />, 35 document.getElementById('example') 36 ); 37 </script> 38 </body> 39 </html>
实验
将上行例子中的18行注释后, 运行效果。
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="UTF-8" /> 5 <script src="../build/react.development.js"></script> 6 <script src="../build/react-dom.development.js"></script> 7 <script src="../build/babel.min.js"></script> 8 </head> 9 <body> 10 <div id="example"></div> 11 <script type="text/babel"> 12 class LikeButton extends React.Component { 13 constructor(props) { 14 super(props) 15 this.state = { 16 liked: false 17 } 18 //this.handleClick = this.handleClick.bind(this) 19 } 20 handleClick(event) { 21 this.setState({ liked: !this.state.liked }); 22 } 23 render() { 24 var text = this.state.liked ? 'like' : 'haven\'t liked'; 25 return ( 26 <p onClick={this.handleClick}> 27 You {text} this. Click to toggle. 28 </p> 29 ); 30 } 31 } 32 33 ReactDOM.render( 34 <LikeButton />, 35 document.getElementById('example') 36 ); 37 </script> 38 </body> 39 </html>
浏览器运行结果,控制台有报错:
思考
本来以为是 babel把es6翻译成es5特殊要求导致。
最后找到问题根因是,事件处理handler引入的特殊要求, 因为ReactJS使用了 virtual DOM, 生成的组件是虚拟的,并不是页面上真实显示的控件。
对于页面上真实存在的控件, 在事件处理的handler中, 使用this表示控件本身。
例如:
http://www.w3school.com.cn/tiy/t.asp?f=hdom_onclick
第一个输入框中添加click事件, 使用 this.value 获取控件的 当前值。
<html> <body> Field1: <input type="text" id="field1" value="Hello World!" onclick="alert(this.value)"> <br /> Field2: <input type="text" id="field2"> <br /><br /> Click the button below to copy the content of Field1 to Field2. <br /> <button onclick="document.getElementById('field2').value= document.getElementById('field1').value; alert(this.text)">Copy Text</button> </body> </html>
但是 ReactJS设计上, 将UI DOM 和实际上的 virtual DOM进行分离, 实际逻辑在virtual DOM上, 对于本例子, 就是需要将 目标 事件 handler 绑定到 虚拟DOM上。
UI dom上视图组件,调用绑定过this的事件handler。