React中的this绑定

发布于:2025-08-01 ⋅ 阅读:(11) ⋅ 点赞:(0)

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. 事件参数传递

    1. 在执行事件函数时,可能需要获取一些参数信息: 比如event对象、其他参数
    1. 情况一: 获取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>
      
    1. 情况二:获取更多参数
    • 有更多参数时,最好的方式就是传入一个箭头函数,主动执行的事件函数,并且传入相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>
      
      

网站公告

今日签到

点亮在社区的每一天
去签到