vuejs data 属性中的 this 指向问题
vuejs data 属性中的 this 指向问题
场景
之前在封装 table 组件 BasicTableVue 的时候遇到的问题,在 data 属性中无法使用 this.** 调用 methods 中的函数。
例如下面的代码
1 | class BasicTableData { |
吾辈尝试了一下原生的 vuejs,发现这样的 data 仍然不能用。
解决
后来在官方文档找到了 这里,data 如果是一个对象或者箭头函数时,不会绑定 this,仅当 data 是一个普通函数(使用 function 声明)时,才会被绑定 this。
那么,知道了原因,解决方案就很简单了。
- 如果需要使用在
data中使用this调用methods中的函数,则data必须声明为普通函数 - 如果需要默认
datadefaultData,则Table可以将合并后的data声明为函数,并将defaultData与data(使用Table创建实例时传入的)的返回值合并
修改后的代码如下
1 | class BasicTableData { |
思考
现在问题解决了,那么,为什么 vuejs 就能够在传入 data 函数时就能调用 methods 中的函数了呢?吾辈稍微 debug 进入源码看了一下
创建
Table进入构造函数
因为继承了 Vue,所以进入 Vue 的构造函数中

因为当前实例属于 Vue,所以进入
_init进行初始化
跳转到
initState(vm);处,该函数将对 data 属性进行初始化(至于为什么是 state 可能是因为最初就是模仿 react 写的?)
进入到
initState(),跳转到initData(vm);处
进入到
initData()函数,看到了判断逻辑
1
2var data = vm.$options.data
data = vm._data = typeof data === 'function' ? getData(data, vm) : data || {}注意看,这里的 vue 内部判断了 data 是否为函数,如果是就去
getData(data, vm)进入
getData()函数看看,发现了关键代码
1
return data.call(vm, vm)
是的,data 调用时使用
call绑定this为 vm,而此时vm.calcTime已经有值了。那么,
vm.calcTime是什么时候被初始化的呢?
其实也在initState函数中,可以看到,vue 的初始化顺序是props: 外部传递的属性methods: 组件的函数data: 组件的属性computed: 计算属性watch: 监听函数

总结
相比于 react,vue 做了更多的 黑魔法 呢!就像 this 指向问题,react 是交由用户自行解决的,而 vue 则在后面偷偷的为函数绑定 this 为 vue 实例本身。