vue data 属性中的 this 指向问题
本文最后更新于:2021年6月21日 中午
场景
之前在封装 table 组件 Vue 表格封装 BasicTableVue 的时候遇到的问题,在 data
属性中无法使用 this.**
调用 methods
中的函数。
例如下面的代码
1 |
|
吾辈尝试了一下原生的 vuejs,发现这样的 data 仍然不能用。
解决
后来在官方文档找到了 这里,data 如果是一个对象或者箭头函数时,不会绑定 this
,仅当 data
是一个普通函数(使用 function
声明)时,才会被绑定 this
。
那么,知道了原因,解决方案就很简单了。
- 如果需要使用在
data
中使用this
调用methods
中的函数,则data
必须声明为普通函数 - 如果需要默认
data
defaultData
,则Table
可以将合并后的data
声明为函数,并将defaultData
与data
(使用Table
创建实例时传入的)的返回值合并
修改后的代码如下
1 |
|
思考
现在问题解决了,那么,为什么 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 实例本身。