vue2项目中 箭头函数和普通函数里面 this的指向有何不同?

vue2项目中 箭头函数和普通函数里面 this的指向有何不同?

在 Vue2 项目中,箭头函数和普通函数中的 this 指向有所不同。理解这种差异对于正确使用 Vue 组件内的方法非常重要。

普通函数中的 this

在 Vue 组件中,普通函数(也称为函数声明或函数表达式)中的 this 通常指向 Vue 实例。这意味着你可以在这些函数内部访问组件的数据、属性、方法等。

例如:

export default {
  data() {
    return {
      message: 'Hello, Vue!'
    };
  },
  methods: {
    logMessage() {
      console.log(this.message); // 输出: Hello, Vue!
    }
  }
};

在这个例子中,logMessage 是一个普通函数,它的 this 永远指向 Vue 实例,因此可以正常访问 data 中的 message

箭头函数中的 this

箭头函数不会创建自己的 this 上下文,而是继承父作用域的 this 值。这意味着在 Vue 组件的方法中使用箭头函数时,this 不会指向 Vue 实例,而是指向定义该箭头函数的作用域中的 this

例如:

export default {
  data() {
    return {
      message: 'Hello, Vue!'
    };
  },
  methods: {
    logMessage: () => {
      console.log(this.message); // 输出: undefined 或其他值,取决于外部上下文
    }
  }
};

在这个例子中,logMessage 是一个箭头函数,它的 this 指向的是定义该箭头函数的作用域中的 this,而不是 Vue 实例。因此,this.message 会是 undefined 或者其他值,这取决于外部作用域中的 this

何时使用箭头函数

  • 事件处理器:在某些情况下,你可能会在模板中直接使用内联箭头函数作为事件处理器。这样做会导致 this 指向全局对象(如浏览器环境下的 window),因此不推荐这样做。

    <button @click="() => this.logMessage()">Click me</button>
    

    更好的做法是在 methods 中定义一个普通函数,并将其绑定到事件处理器。

    <button @click="logMessage">Click me</button>
    
  • 生命周期钩子:Vue 的生命周期钩子应该总是使用普通函数,以确保 this 正确地指向 Vue 实例。

    export default {
      mounted() {
        console.log(this.message); // 输出: Hello, Vue!
      }
    };
    
  • 回调函数:如果你需要在回调函数中使用 this,并且希望它指向 Vue 实例,可以使用普通函数或者使用 .bind(this) 方法来显式绑定 this

    export default {
      methods: {
        async fetchData() {
          await someAsyncFunction().then(function(response) {
            console.log(this.message); // 输出: undefined
          }.bind(this));
          
          // 或者使用箭头函数
          await someAsyncFunction().then((response) => {
            console.log(this.message); // 输出: Hello, Vue!
          });
        }
      }
    };
    

总结来说,在 Vue2 项目中,为了确保 this 指向 Vue 实例,你应该在大多数情况下使用普通函数。只有在特定场景下,比如在回调函数中保持 this 上下文一致时,才考虑使用箭头函数。

如果在methods中有个chat方法,使用普通函数形式,里面有一个 run方法也使用普通函数形式,run方法中使用this,那么此时this的指向是?

在 Vue2 项目中,如果你在 methods 中定义了一个普通函数 chat,并且在这个 chat 方法中又定义了另一个普通函数 run,那么 run 方法中的 this 指向取决于 run 函数是如何被调用的。

情况 1: 直接在 chat 方法中调用 run 方法

如果 run 方法是在 chat 方法内部直接调用的,那么 run 方法中的 this 仍然会指向 Vue 实例。这是因为 run 方法继承了 chat 方法的 this 上下文。

export default {
  data() {
    return {
      message: 'Hello, Vue!'
    };
  },
  methods: {
    chat() {
      function run() {
        console.log(this.message); // 输出: Hello, Vue!
      }
      run();
    }
  }
};

在这种情况下,run 方法中的 this 指向 Vue 实例,因此可以正常访问 data 中的 message

情况 2: run 方法作为回调函数传递

如果 run 方法是作为回调函数传递给其他方法或异步操作(如 setTimeoutPromisethencatch),那么 run 方法中的 this 将不再指向 Vue 实例,而是指向全局对象(在浏览器环境中通常是 window)或其他上下文。

export default {
  data() {
    return {
      message: 'Hello, Vue!'
    };
  },
  methods: {
    chat() {
      function run() {
        console.log(this.message); // 输出: undefined (在浏览器中)
      }

      // 作为 setTimeout 的回调
      setTimeout(run, 1000);

      // 作为 Promise 的 then 回调
      someAsyncFunction().then(run);
    }
  }
};

在这种情况下,run 方法中的 this 不再指向 Vue 实例,而是指向全局对象 window,因此 this.message 会是 undefined

解决方法

为了确保 run 方法中的 this 始终指向 Vue 实例,你可以使用以下几种方法:

1. 使用箭头函数

箭头函数不会创建自己的 this 上下文,而是继承父作用域的 this 值。

export default {
  data() {
    return {
      message: 'Hello, Vue!'
    };
  },
  methods: {
    chat() {
      const run = () => {
        console.log(this.message); // 输出: Hello, Vue!
      };

      // 作为 setTimeout 的回调
      setTimeout(run, 1000);

      // 作为 Promise 的 then 回调
      someAsyncFunction().then(run);
    }
  }
};

2. 显式绑定 this

使用 .bind(this) 方法来显式绑定 this

export default {
  data() {
    return {
      message: 'Hello, Vue!'
    };
  },
  methods: {
    chat() {
      function run() {
        console.log(this.message); // 输出: Hello, Vue!
      }

      // 作为 setTimeout 的回调
      setTimeout(run.bind(this), 1000);

      // 作为 Promise 的 then 回调
      someAsyncFunction().then(run.bind(this));
    }
  }
};

3. 在 chat 方法中保存 this 引用

chat 方法中保存 this 引用,然后在 run 方法中使用这个引用。

export default {
  data() {
    return {
      message: 'Hello, Vue!'
    };
  },
  methods: {
    chat() {
      const self = this;

      function run() {
        console.log(self.message); // 输出: Hello, Vue!
      }

      // 作为 setTimeout 的回调
      setTimeout(run, 1000);

      // 作为 Promise 的 then 回调
      someAsyncFunction().then(run);
    }
  }
};

通过这些方法,你可以确保 run 方法中的 this 指向 Vue 实例,从而正确地访问组件的数据和方法。

如果run方法是在 requestAnimationFrame中调用呢?

在 Vue2 项目中,如果你在 methods 中定义了一个普通函数 chat,并且在这个 chat 方法中使用 requestAnimationFrame 调用另一个普通函数 run,那么 run 方法中的 this 指向取决于 requestAnimationFrame 的调用方式。

情况分析

run 方法作为 requestAnimationFrame 的回调函数时,run 方法中的 this 将不再指向 Vue 实例,而是指向全局对象(在浏览器环境中通常是 window)。

示例代码

export default {
  data() {
    return {
      message: 'Hello, Vue!'
    };
  },
  methods: {
    chat() {
      function run() {
        console.log(this.message); // 输出: undefined (在浏览器中)
      }

      requestAnimationFrame(run);
    }
  }
};

在这种情况下,run 方法中的 this 不再指向 Vue 实例,因此 this.message 会是 undefined

解决方法

为了确保 run 方法中的 this 始终指向 Vue 实例,你可以使用以下几种方法:

1. 使用箭头函数

箭头函数不会创建自己的 this 上下文,而是继承父作用域的 this 值。

export default {
  data() {
    return {
      message: 'Hello, Vue!'
    };
  },
  methods: {
    chat() {
      const run = () => {
        console.log(this.message); // 输出: Hello, Vue!
      };

      requestAnimationFrame(run);
    }
  }
};

2. 显式绑定 this

使用 .bind(this) 方法来显式绑定 this

export default {
  data() {
    return {
      message: 'Hello, Vue!'
    };
  },
  methods: {
    chat() {
      function run() {
        console.log(this.message); // 输出: Hello, Vue!
      }

      requestAnimationFrame(run.bind(this));
    }
  }
};

3. 在 chat 方法中保存 this 引用

chat 方法中保存 this 引用,然后在 run 方法中使用这个引用。

export default {
  data() {
    return {
      message: 'Hello, Vue!'
    };
  },
  methods: {
    chat() {
      const self = this;

      function run() {
        console.log(self.message); // 输出: Hello, Vue!
      }

      requestAnimationFrame(run);
    }
  }
};

总结

无论你选择哪种方法,关键是要确保 run 方法中的 this 指向 Vue 实例。以下是三种方法的总结:

  1. 使用箭头函数:最简洁的方法,适合大多数情况。
  2. 显式绑定 this:通过 .bind(this) 方法显式绑定 this
  3. 保存 this 引用:在 chat 方法中保存 this 引用,并在 run 方法中使用该引用。

选择一种适合你项目需求的方法,可以确保 this 正确地指向 Vue 实例。

posted @   龙陌  阅读(113)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示