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); // 作为 Promisethen 回调 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 实例。


__EOF__

本文作者龙陌
本文链接https://www.cnblogs.com/longmo666/p/18511954.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   龙陌  阅读(107)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)
点击右上角即可分享
微信分享提示