状态数据初始化
目录
该章节要解答的疑惑有:
- 为什么通过
vm.xxx
可以访问到props
和data
数据?
initState
组件实例化的过程中,会在vm._init
里调用initState()
对组件实例上的状态数据进行初始化,包括:
export function initState (vm: Component) {
vm._watchers = []
const opts = vm.$options
if (opts.props) initProps(vm, opts.props)
if (opts.methods) initMethods(vm, opts.methods)
if (opts.data) {
initData(vm)
} else {
observe(vm._data = {}, true /* asRootData */)
}
if (opts.computed) initComputed(vm, opts.computed)
if (opts.watch && opts.watch !== nativeWatch) {
initWatch(vm, opts.watch)
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
proxy
无论是组件的props
数据还是data
数据,最终都可以在组件实例vm
上访问到,因为在initProps
和initData
时都调用了proxy
将vm._props
和vm._data
上的数据都代理到了vm
上。
// initProps 里
proxy(vm, `_props`, key)
// initData 里
proxy(vm, `_data`, key)
1
2
3
4
5
2
3
4
5
其实proxy
的实现特别简单,就是通过Object.defineProperty
在vm
上新增加了一属性,属性访问器描述符的get
特性就是获取vm._props[key]
(以props
为例)的值并返回,属性的访问器描述符的set
特性就是设置vm._props[key]
的值。
因此,我们最终在访问props
时,对vm.xxx
的读写实际上就是对vm._props.xxx
的读写。data
也是同理。
const sharedPropertyDefinition = {
enumerable: true,
configurable: true,
get: noop,
set: noop
}
export function proxy (target: Object, sourceKey: string, key: string) {
sharedPropertyDefinition.get = function proxyGetter () {
return this[sourceKey][key]
}
sharedPropertyDefinition.set = function proxySetter (val) {
this[sourceKey][key] = val
}
Object.defineProperty(target, key, sharedPropertyDefinition)
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
computed
也是经过类似的处理,只是get
和set
不一样而已。