React中的this绑定
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() -> obj3. 显示绑定:call\apply\bind foo.call('aaa') -> String('aaa')4. new绑定:new foo() -> 创建一个新对象,并且赋值给this*/ // 1.定义App根组件class App extends React.Component {// class fieldsname = '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.statereturn (<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.statereturn (<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, thisconsole.log('btnClick', event, this)console.log('name,age==', name, age)} render () {const { message } = this.statereturn (<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>