目录
声明式渲染
data 必须是一个函数
为什么 data 必须是一个函数?
提一个 data 作为箭头函数的写法
源码
声明式渲染
这是学习vue开发,必先了解的第一个特征。如前已经实现的App.vue
组件,已经包括声明式渲染:
<template>
<div>{{message}}</div>
</template>
<script>
export default {
name: 'App',
components: {},
data: () => ({
message:'hi'
}),
};
</script>
message
是在data
中声明的一个文本,直接以{{message}}
内嵌于模板中。当message
改变时,模板会自动更新。
这是由于vue2
基于Object.defineProperty()
给data
中的每个属性定义了一对setter/getter
。当模板渲染时,getter被调用,视图依赖的数据项被记录下来;当数据改变时,检查改变的数据有没有被依赖,如果有,重新渲染视图。
这就是MVVM
框架在view
与data-view
之间实现的BI-DataBinding
机制。
data 必须是一个函数
如果直接返回一个对象,在vue-cli3
中,编译阶段直接就报错了。
vue
组件的导出是唯一的,如果返回的是一个对象,那么所有该组件的实例将共享同一块内存的数据对象,改变任何一个组件实例的数据,其它均会受到影响。
例如,将App.vue
修改为:
<template>
<div>
<HellWorld></HellWorld>
<HellWorld></HellWorld>
<HellWorld></HellWorld>
</div>
</template>
<script>
import HellWorld from './HelloWorld.vue'
export default {
name: 'App',
components: {HellWorld},
};
</script>
并新增一个HelloWorld.vue
组件:
<template>
<div @click="message ='!'">{{message}}</div>
</template>
<script>
const data = {
message:'hi'
}
export default {
name: 'HelloWorld',
components: {},
data: ()=>data,
};
</script>
当单击div
时,message
尾部追求一个符号。data
虽然是一个函数,但是返回的却是一个const
对象。const data
在项目仅会声明一次,在多个组件实例中是唯一的。
如图所示,单击任何一个组件,其它组件亦受影响:
解决方法也很简单,直接让data
返回一个局部的临时对象:
<script> // const data = { // message:'hi' // } export default { name: 'HelloWorld', components: {}, data: ()=>({ message:'hi' }), }; </script>
运行效果:
为什么 data 必须是一个函数?
这是vue2
内部源码要求的。通过查看Vue->_init->initState->initData
源码:
发现,如果data
未定义,一个默认的data
对象会被创建,否则data
会被当成一个function
被调用。
而在initData
中,data function
被以call
的方式调用了:
其中pushTarget()
,疑为对data observer
的处理。
即使data function
是一个函数,也仅是在初始化时调用一次,然后函数返回的值就一直保存在了vm._data
上。在后续的运行时数据发生时,改变的也是vm._data
,这个对象在组件的生命内,其引用一直保持不变。
提一个 data 作为箭头函数的写法
细心的读者会发现,data function
没有return
:
data: ()=>({
message:'hi'
}),
这是一个箭头函数,当函数体代码只有一句时, return
可以省略。
那么,花括号外面的()
能不能省略?
不能,因为函数返回的是一个字面值对象。如果这里的()
省略了,编译器不清楚后面的{}
究竟表示对象,还是函数的边界了。
源码
https://git.code.tencent.com/shiqiaomarong/vue-go-rapiddev-example/tags/v20200108
参考链接
- https://www.liaoxuefeng.com/wiki/1022910821149312/1031549578462080
- https://juejin.im/entry/59225ff8a22b9d005885cb15
- https://blog.rxliuli.com/p/2f1f8cdf/