stateMixin(Vue) // 挂载状态处理方法(挂载data,methods等)
eventsMixin(Vue) // 挂载 事件 的方法( o n , on, on,off等)
lifecycleMixin(Vue) // 挂载 生命周期方法(update,destory)
renderMixin(Vue) // 挂载与渲染有关的方法($nextTick,_render)
每个方法可以按照代码逻辑来看,实现对应功能,这里拿initMixin
举例
篇幅有限,所有此处仅解释initMixin逻辑,剩余几个方法大家可以自己探索哦
initMixin
initMixin
中仅仅挂载了_init()
方法,在_init
中,初始化了整个vue
的状态:
function _init(option) {
…
vm._uid = uid++ // 即component id
…
initLifecycle(vm)
initEvents(vm)
initRender(vm)
callHook(vm, ‘beforeCreate’)
initInjections(vm) // resolve injections before data/props
initState(vm)
initProvide(vm)
callHook(vm, ‘created’)
…
if (vm.$options.el) {
vm. m o u n t ( v m . mount(vm. mount(vm.options.el) // 开始挂载
}
}
这里我们可以看到几个beforeCreate
,created
和Mount
关键字,大概就能够猜到vu
e实例的部分生命周期方法就是在这里进行了挂载,再结合 vue官方文档的图示
关于初始化整个vue
的状态,可以举例来说,例如initLifecycle
中就赋值了parent,children
,以及一些isMounted,isDestroy
的标识符。initRender
中就将attrs,listeners
响应化,等等,诸如此类。
从initMixin=>initState=>initData
,便可以看到挂载props,methods,data,computed,watch
了,
可以看到,此处先挂载了
props,methods
,然后是data
的顺序,其实再往下探究逻辑就可以知道,如果存在变量重名,优先级是props>methods>data
的,这也就解释了为什么初始化的顺序是这样安排的
在initData
中,先是获取了data
数据,判断props,methods
变量重名问题,然后是走了一个代理,将变量名代理到vue
实例上,这样的话你的vue
实例中,使用this.x
指向就可以访问到this.data.x,
这类代理也用在了props
和methods
中
在
initData
获取数据中可以看到一个判断typeof data === 'function' ? getData(data, vm) : data || {}
, 支持两种方式获取,实际上如果是自己写这样一个逻辑是会藏有隐患的,如果你的data是直接使用对象,而js的复杂数据类型是地址引用,这意味着,你实例化了两个vue
对象,实际上他们的data引用地址是同一个地址,对其中一个vue data
的修改会触发另一个vue数据的变动,带来的问题是巨大的
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, sharedPropertyDefi