05-React中绑定this并给函数传参的几种方式

前言

我们先来看下面这段代码:

components/MyComponent.jsx

  1. import React from "react";
  2. export default class MyComponent extends React.Component {
  3. constructor(props) {
  4. super(props);
  5. this.state = {
  6. msg: "这是 MyComponent 组件 默认的msg"
  7. };
  8. }
  9. render() {
  10. return (
  11. <div>
  12. <h1>绑定This并传参</h1>
  13. <input type="button" value="绑定this并传参" onClick={this.changeMsg} />
  14. <h3>{this.state.msg}</h3>
  15. </div>
  16. );
  17. }
  18. changeMsg() {
  19. // 注意:这里的changeMsg()只是一个普通方法。因此,在触发的时候,这里的 this 是 undefined
  20. console.log(this); // 打印结果:undefined
  21. this.setState({
  22. msg: "设置 msg 为新的值"
  23. });
  24. }
  25. }

上面的代码中,点击按钮,执行 changeMsg() 方法,尝试修改 this.state.msg 的值。但是,这个方法执行的时候,是会报错的:

  1. Uncaught TypeError: Cannot read property 'setState' of null

而且,打印this的结果也是 undefined。这是为啥呢?因为这里的 this 并不是指向 MyComponent 组件本身。

那如何让 changeMsg() 方法里面的 this,指向MyComponent 组件呢?办法总是有的,比如说,将changeMsg() 修改为箭头函数:

  1. changeMsg = () => {
  2. console.log(this); // 打印结果:MyComponent 组件
  3. this.setState({
  4. msg: "设置 msg 为新的值"
  5. });
  6. };

那么,除了箭头函数可以 绑定 this,还有没有其他的方式呢?我们接下来讲一讲。

绑定 this 的方式一:bind()

代码举例:

  1. import React from "react";
  2. export default class MyComponent extends React.Component {
  3. constructor(props) {
  4. super(props);
  5. this.state = {
  6. msg: "这是 MyComponent 组件 默认的msg"
  7. };
  8. }
  9. render() {
  10. return (
  11. <div>
  12. <h1>绑定This并传参</h1>
  13. {/* bind 的作用:为前面的函数,修改函数内部的 this 指向。让 函数内部的this,指向 bind 参数列表中的 第一个参数 */}
  14. <input
  15. type="button"
  16. value="绑定this并传参"
  17. onClick={this.changeMsg1.bind(this)}
  18. />
  19. <h3>{this.state.msg}</h3>
  20. </div>
  21. );
  22. }
  23. changeMsg1() {
  24. this.setState({
  25. msg: "设置 msg 为新的值"
  26. });
  27. }
  28. }

上方代码中,我们为什么用 bind(),而不是用 call/apply 呢?因为 bind() 并不会立即调用,正是我们需要的。

注意:bind 中的第一个参数,是用来修改 this 指向的。第一个参数后面的所有参数,都将作为函数的参数传递进去。

我们来看看通过 bind() 是怎么传参的。

通过 bind() 绑定this,并给函数传参

  1. import React from "react";
  2. export default class MyComponent extends React.Component {
  3. constructor(props) {
  4. super(props);
  5. this.state = {
  6. msg: "这是 MyComponent 组件 默认的msg"
  7. };
  8. }
  9. render() {
  10. return (
  11. <div>
  12. <h1>绑定This并传参</h1>
  13. {/* bind 的作用:为前面的函数,修改函数内部的 this 指向。让 函数内部的this,指向 bind 参数列表中的 第一个参数 */}
  14. <input type="button" value="绑定this并传参" onClick={this.changeMsg1.bind(this, "千古啊", "壹号啊")} />
  15. <h3>{this.state.msg}</h3>
  16. </div>
  17. );
  18. }
  19. changeMsg1(arg1, arg2) {
  20. this.setState({
  21. msg: "设置 msg 为新的值" + arg1 + arg2
  22. });
  23. }
  24. }

绑定 this 并给函数传参 的方式二:构造函数里设置 bind()

我们知道,构造函数中的 this 本身就是指向组件的实例的,所以,我们可以在这里做一些事情。

代码举例:

  1. import React from "react";
  2. export default class MyComponent extends React.Component {
  3. constructor(props) {
  4. super(props);
  5. this.state = {
  6. msg: "这是 MyComponent 组件 默认的msg"
  7. };
  8. // 绑定 this 并给函数传参的方式2: 在构造函数中绑定并传参
  9. // 注意:当一个函数调用 bind 改变了this指向后,bind 函数调用的结果,有一个【返回值】,这个值,就是被改变this指向后的函数的引用。
  10. // 也就是说: bind 不会修改 原函数的 this 指向,而是改变了 “函数拷贝”的this指向。
  11. this.changeMsg2 = this.changeMsg2.bind(this, "千古恩", "壹号恩");
  12. }
  13. render() {
  14. return (
  15. <div>
  16. <h1>绑定This并传参</h1>
  17. <input type="button" value="绑定this并传参" onClick={this.changeMsg2} />
  18. <h3>{this.state.msg}</h3>
  19. </div>
  20. );
  21. }
  22. changeMsg2(arg1, arg2) {
  23. this.setState({
  24. msg: "设置 msg 为新的值" + arg1 + arg2
  25. });
  26. }
  27. }

上方代码中,需要注意的是:当一个函数调用 bind 改变了this指向后,bind 函数调用的结果,有一个【返回值】,这个值,就是被改变this指向后的函数的引用。也就是说: bind 不会修改 原函数的 this 指向,而是改变了 “函数拷贝”的this指向。

绑定 this 并给函数传参 的方式三:箭头函数【荐】

第三种方式用得最多。

代码举例:

  1. import React from "react";
  2. export default class MyComponent extends React.Component {
  3. constructor(props) {
  4. super(props);
  5. this.state = {
  6. msg: "这是 MyComponent 组件 默认的msg"
  7. };
  8. }
  9. render() {
  10. return (
  11. <div>
  12. <h1>绑定This并传参</h1>
  13. <input
  14. type="button"
  15. value="绑定this并传参"
  16. onClick={() => {
  17. this.changeMsg3("千古3", "壹号3");
  18. }}
  19. />
  20. <h3>{this.state.msg}</h3>
  21. </div>
  22. );
  23. }
  24. changeMsg3 = (arg1, arg2) => {
  25. // console.log(this);
  26. // 注意:这里的方式,是一个普通方法,因此,在触发的时候,这里的 this 是 undefined
  27. this.setState({
  28. msg: "绑定this并传参的方式3:" + arg1 + arg2
  29. });
  30. };
  31. }