Vue.js方法中Promise回调内无法访问Vue上下文的问题求助
问题分析与解决方案
嘿,我刚好碰到过类似的坑,来帮你捋清楚为啥会出现这个问题,以及怎么解决~
为啥箭头函数里的this会变成undefined?
你说的没错,这确实和你用VueContext的模块声明方式,以及JSFiddle里直接new Vue()的写法差异有关。
正常来说,ES6箭头函数会继承外层作用域的this,但这里出问题的核心原因是:
- 在JSFiddle里,你把方法直接写在
new Vue()的methods选项里,Vue会自动帮你把方法的this绑定成组件实例(也就是你看到的VueComponent),所以内部的箭头函数回调自然能继承到这个this。 - 但如果你的方法是写在单独的模块文件里,再通过
VueContext引入或绑定,情况就变了:- 要是模块里的方法是用箭头函数写的,那它的
this会直接绑定到模块的顶层上下文(在ES模块规范里,顶层this就是undefined),就算你把它挂载到组件里,这个箭头函数的this已经固定死了,内部的回调箭头函数自然也继承到undefined。 - 就算模块里用的是普通函数,如果
VueContext没有正确帮你把组件实例绑定到方法的this上,那外层方法的this就不是组件实例,内部回调自然也拿不到正确的上下文。
- 要是模块里的方法是用箭头函数写的,那它的
举个错误的模块写法例子,你一看就懂:
// 模块文件里的错误写法——用箭头函数定义方法 export const handleClick = () => { console.log('外层方法的this:', this); // 这里已经是undefined了 fetchSomeData().then(() => { console.log('回调里的this:', this); // 当然也是undefined }) }
而JSFiddle里的正确写法,Vue自动帮你处理了绑定:
new Vue({ methods: { handleClick() { // 普通函数,Vue自动绑定this为组件实例 fetchSomeData().then(() => { console.log('回调里的this:', this); // 正确拿到VueComponent }) } } })
怎么解决这个问题?
给你几个针对性的方案,挑适合你场景的用:
1. 模块里的方法改用普通函数声明
这是最推荐的方案,只要把模块里的箭头函数改成普通函数,Vue在挂载方法到组件时,就会自动帮你把组件实例绑定到方法的this上:
// 模块文件里的正确写法 export function handleClick() { fetchSomeData().then(() => { console.log('回调里的this:', this); // 现在就是Vue组件实例啦 this.yourDataProperty = '更新后的值'; }) }
然后在组件里正常引入并挂载到methods:
import { handleClick } from './your-module.js' export default { methods: { handleClick // Vue会自动帮你绑定this } }
2. 手动给方法绑定组件实例
如果因为某些原因必须用箭头函数写模块里的方法,那可以在组件里手动把组件实例绑定到方法上:
import { handleClick } from './your-module.js' export default { methods: { // 手动绑定this为组件实例 handleClick: handleClick.bind(this) } } // 或者在created钩子里面绑定,效果一样 created() { this.handleClick = handleClick.bind(this) }
3. 提前缓存组件实例的this
要是不想改方法的声明方式,还有个简单的办法:在方法开头把组件实例的this存到一个变量里(比如vm),然后在回调里用这个变量代替this:
// 组件方法里的写法 handleClick() { const vm = this; // 先把组件实例存起来 fetchSomeData().then(() => { console.log('用vm访问上下文:', vm); // 直接用vm就能操作组件数据、方法了 vm.yourDataProperty = '新值'; }) }
4. 检查VueContext的初始化方式
最后别忘了确认你的VueContext是正确创建的组件实例,而不是一个没被实例化的构造函数。比如如果VueContext是用Vue.extend创建的组件构造器,那你得确保是通过new VueContext()或者在Vue组件树里正确使用它,这样内部的方法才能拿到正确的this绑定。
快速验证小技巧
你可以在模块方法的开头加一行打印,看看外层方法的this是什么:
export function handleClick() { console.log('方法外层的this:', this); // 如果是undefined,说明Vue没绑定成功 fetchSomeData().then(() => { console.log('回调里的this:', this); }) }
要是外层的this就是undefined,那问题肯定出在方法的绑定上,用上面的方案1或2就能解决~
内容的提问来源于stack exchange,提问作者Brad Orego
相关产品推荐
相关产品推荐

