1. this的绑定问题
- 1.1. 在事件执行后,需要获取当前类的对象中相关的属性,这个时候需要用到this
- 如果这里直接打印this, 也会发现它是一个undefined
- 1.2. 为什么是undefined呢?
- 原因是btnClick函数并不是我们主动调用的,而且当button发生改变时,React内部调用了btnClick函数;
- 而它内部调用时,并不知道要如何绑定正确的this;
- 1.3. 如何解决this的问题
- 方案一:
bind给btnClick显示绑定this
- 方案二:
使用ES6 class fields语法
- 方案三: 事件监听时传入
箭头函数(个人推荐)
- 示例代码如下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <div id="root"></div> <script src="../lib/react.js"></script> <script src="../lib/react-dom.js"></script> <script src="../lib/babel.js"></script> <script type="text/babel"> const obj = { name: 'obj', foo: function () { console.log('foo:', this); } } // obj.foo(); const config = { onClick: obj.foo.bind(obj) } const click = config.onClick; click(); // 默认绑定 -> (非严格模式)window -> (严格模式下)undefined /* this的四种绑定规则: 1. 默认绑定,独立执行 foo() 2. 隐式绑定, 被一个对象执行 obj.foo() -> obj 3. 显示绑定:call\apply\bind foo.call('aaa') -> String('aaa') 4. new绑定:new foo() -> 创建一个新对象,并且赋值给this */ // 1.定义App根组件 class App extends React.Component { // class fields name = 'App' constructor () { super() this.state = { message: 'hello world', counter: 100 } this.btn1Click = this.btn1Click.bind(this) } btn1Click () { console.log('btn1Click', this); this.setState({ counter: this.state.counter + 1 }) } btn2Click = () => { console.log('btn2Click', this); this.setState({ counter: this.state.counter + 1 }) } btn3Click () { console.log('btn3Click', this); this.setState({ counter: this.state.counter + 1 }) } render () { const { message } = this.state return ( <div> {/* this.btn1Click是隐式绑定,但是没有调用, 所以this是undefined,只是引用这个函数的地址,相当于把这个函数的内存地址传进去了, 实际上是传给了React.createElement('button', {onCLick: this.btn1Click}), 当按钮发生点击时,就会去调这个函数 const click = config.onClick, 当内部发生点击时是直接调用click(), 如果是直接独立函数调用就是this绑定规则里面的默认绑定 */} {/* 1. this绑定方式一: bind绑定 */} <button onClick={ this.btn1Click }>按钮1</button> {/* 2. this绑定方式二: ES6 class fields本质还是箭头函数 */} <button onClick={ this.btn2Click }>按钮2</button> {/* 3. this绑定方式三: 直接传入一个箭头函数*/} <button onClick={ () => { console.log('btn3Click') } }>按钮3</button> <button onClick={ () => { this.btn3Click() } }>按钮3</button> <h2>当前计数: { this.state.counter }</h2> </div> ) } } // 2. 创建root并且渲染App组件 const root = ReactDOM.createRoot(document.querySelector('#root')) root.render(<App/>) </script> </body> </html>
- 方案一:
2. 事件参数传递
-
- 在执行事件函数时,可能需要获取一些参数信息: 比如event对象、其他参数
-
- 情况一: 获取event对象
- 很多时候需要拿到event对象来做一些事情(比如组织默认行为)
- 默认情况下,event对象有被直接传入,函数可以直接获取到event对象
- 示例代码如下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <div id="root"></div> <script src="../lib/react.js"></script> <script src="../lib/react-dom.js"></script> <script src="../lib/babel.js"></script> <script type="text/babel"> // function foo (name, age, height) { } // const bar = foo.bind('aaa', 'kobe', 30) // bar('event') // 1.定义App根组件 class App extends React.Component { constructor () { super() this.state = { message: 'hello world', counter: 100 } } btnClick(event) { console.log('btnClick', event, this) } render () { const { message } = this.state return ( <div> {/* 1. event参数传递 */} <button onClick={this.btnClick.bind(this)}>按钮1</button> <button onClick={(event) => this.btnClick(event)}>按钮2</button> </div> ) } } // 2. 创建root并且渲染App组件 const root = ReactDOM.createRoot(document.querySelector('#root')) root.render(<App/>) </script> </body> </html>
-
- 情况二:获取更多参数
- 有更多参数时,最好的方式就是传入一个箭头函数,主动执行的事件函数,并且传入相3. 关的其他参数;
- 实例代码如下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <div id="root"></div> <script src="../lib/react.js"></script> <script src="../lib/react-dom.js"></script> <script src="../lib/babel.js"></script> <script type="text/babel"> // function foo (name, age, height) { } // const bar = foo.bind('aaa', 'kobe', 30) // bar('event') // 1.定义App根组件 class App extends React.Component { constructor () { super() this.state = { message: 'hello world', counter: 100 } } btnClick(event, name, age) { // kobe', 18, this console.log('btnClick', event, this) console.log('name,age==', name, age) } render () { const { message } = this.state return ( <div> {/* 1. event参数传递 */} <button onClick={this.btnClick.bind(this)}>按钮1</button> <button onClick={(event) => this.btnClick(event)}>按钮2</button> {/* 2. 额外的参数传递 */} { /* 多个参数传递 bind不推荐*/ } <button onClick={ this.btnClick.bind(this, 'kobe', 18) }>按钮3(不推荐)</button> <button onClick={ (event) => this.btnClick(event, 'kobe', 18) }>按钮4(推荐)</button> </div> ) } } // 2. 创建root并且渲染App组件 const root = ReactDOM.createRoot(document.querySelector('#root')) root.render(<App/>) </script> </body> </html>