Vue 如何在 data 中使用 this 绑定 methods 中的方法?
场景
吾辈需要在 data
块中绑定 methods
的函数,有什么方法可以做到么?
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Document</title>
</head>
<body>
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.11/lodash.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.min.js"></script>
<script>
class Table extends Vue {
constructor({ data, methods, mounted }) {
super({
data,
methods,
mounted,
})
}
}
const table = new Table({
data: {
user: {
birthday: new Date(),
birthdayFormatter: this.calcTime,
},
},
methods: {
calcTime(time) {
console.log(time, this)
},
},
})
console.log(table.$data.user.birthdayFormatter)
</script>
</body>
</html>
现在打印的结果是 undefined
,说明 this
在 data
中就已经被认为是 window
对象了
吾辈将之放到了计算属性中,仍然是没有效果的。
这个问题的本质在于如何在传值的过程中为某个作用域的 this
绑定为 vue
实例本身,而在绑定的时候 vue
实例并未完成创建
class Table extends Vue {
constructor({ data, methods, mounted, computed }) {
super({
data,
methods,
mounted,
computed,
})
}
}
const table = new Table({
methods: {
calcTime(time) {
return time.toISOString()
},
},
computed: {
user: () => ({
birthday: new Date(),
birthdayFormatter: this.calcTime,
}),
},
})
console.log(table.user.birthdayFormatter)
vuejs data 属性中的 this 指向问题
场景
之前在封装 table 组件 BasicTableVue 的时候遇到的问题,在
data
属性中无法使用this.**
调用methods
中的函数。例如下面的代码
吾辈尝试了一下原生的 vuejs,发现这样的 data 仍然不能用。
解决
后来在官方文档找到了 这里,data 如果是一个对象或者箭头函数时,不会绑定
this
,仅当data
是一个普通函数(使用function
声明)时,才会被绑定this
。那么,知道了原因,解决方案就很简单了。
data
中使用this
调用methods
中的函数,则data
必须声明为普通函数data
defaultData
,则Table
可以将合并后的data
声明为函数,并将defaultData
与data
(使用Table
创建实例时传入的)的返回值合并修改后的代码如下
思考
现在问题解决了,那么,为什么
vuejs
就能够在传入data
函数时就能调用methods
中的函数了呢?吾辈稍微 debug 进入源码看了一下Table
进入构造函数_init
进行初始化initState(vm);
处,该函数将对 data 属性进行初始化(至于为什么是 state 可能是因为最初就是模仿 react 写的?)initState()
,跳转到initData(vm);
处进入到

initData()
函数,看到了判断逻辑注意看,这里的 vue 内部判断了 data 是否为函数,如果是就去
getData(data, vm)
进入

getData()
函数看看,发现了关键代码是的,data 调用时使用
call
绑定this
为 vm,而此时vm.calcTime
已经有值了。那么,
vm.calcTime
是什么时候被初始化的呢?其实也在
initState
函数中,可以看到,vue 的初始化顺序是props
: 外部传递的属性methods
: 组件的函数data
: 组件的属性computed
: 计算属性watch
: 监听函数总结
相比于 react,vue 做了更多的 黑魔法 呢!就像 this 指向问题,react 是交由用户自行解决的,而 vue 则在后面偷偷的为函数绑定 this 为 vue 实例本身。