简述VUE组件初始化
http://assets.processon.com/chart_image/5c7361a5e4b03334b528572a.png首先改正了自己的一个想法,生命周期、生命周期钩子是两个不同的概念,不能混为一谈。 其次,由于vue嵌套起来,就像树结构,所以经常看到这种代码/* 就是从父级寻找数据,甚至父..父父级 */parent.$root1、Vue构造函数,一切都在...
http://assets.processon.com/chart_image/5c7361a5e4b03334b528572a.png
首先改正了自己的一个想法,生命周期、生命周期钩子是两个不同的概念,不能混为一谈。
其次,由于vue嵌套起来,就像树结构,所以经常看到这种代码
/* 就是从父级寻找数据,甚至父..父父级 */ parent.$root
1、Vue构造函数,一切都在_init()方法里;
function Vue (options) {
if (!(this instanceof Vue)
) {
warn('Vue is a constructor and should be called with the `new` keyword');
}
this._init(options);
}
2、生成组件ID,然后对options进行一些处理
var vm = this;
vm._uid = uid$3++;
3、然后有一波优化组件的操作,initInternalComponent()方法(我会再研究的,明白了之后再更新)
if (options && options._isComponent) {
// optimize internal component instantiation 优化内部组件实例化
// since dynamic options merging is pretty slow, and none of the 动态选项合并非常慢
// internal component options needs special treatment. 内部组件选项需要特殊处理
initInternalComponent(vm, options);
} else {
vm.$options = mergeOptions(
resolveConstructorOptions(vm.constructor),
options || {},
vm
);
}
/* 注意options._isComponent,反正你new Vue()的时候,是肯定不会执行的,什么时候执行呢? */
new Vue({
el: '#app',
components: {
/* 比如这个子组件,_init()的时候,就会执行这里的代码了 */
ChildComponent:{
create(){
console.log('child-create');
},
},
},
data: {
test: 1
}
})
4、接下来的代码大致就是这样的
initLifecycle(vm);
initEvents(vm);
initRender(vm);
callHook(vm, 'beforeCreate');
initInjections(vm); // resolve injections before data/props
initState(vm);
initProvide(vm); // resolve provide after data/props
callHook(vm, 'created');
4.1、initLifecycle()
初始化生命周期,主要是相关的属性,(按我以前的理解,我还以为是触发钩子呢...)
/* 大致如下 */
vm.$parent = parent;
vm.$root = parent ? parent.$root : vm;
vm.$children = [];
vm.$refs = {};
vm._watcher = null;
vm._inactive = null;
vm._directInactive = false;
vm._isMounted = false;
vm._isDestroyed = false;
vm._isBeingDestroyed = false;
4.2、initEvents()
核心:观察者模式,事件都会被添加到vm._events属性中
解析事件之后,通过$on()添加到vm._events,对于$once()的事件,执行完会调用$off()关闭事件。
使用到方法,updateComponentListeners()、updateListeners() 。
4.3、initRender()
初始化render相关的属性,$attrs、$listeners为响应式属性,其中_parentListeners是上面提到的initInternalComponent()方法生成的。
/* istanbul ignore else */
{
defineReactive$$1(vm, '$attrs', parentData && parentData.attrs || emptyObject, function () {
!isUpdatingChildComponent && warn("$attrs is readonly.", vm);
}, true);
defineReactive$$1(vm, '$listeners', options._parentListeners || emptyObject, function () {
!isUpdatingChildComponent && warn("$listeners is readonly.", vm);
}, true);
}
使用到方法,createElement()、defineReactive()。
4.4、 beforeCreate钩子
略
4.4、 initInjections()
这个是初始化 provide/inject 机制,父组件设置provide,子组件、子...子子组件都可以使用inject接收。
提示:provide
和 inject
绑定并不是可响应的。这是刻意为之的。然而,如果你传入了一个可监听的对象,那么其对象的属性还是可响应的,例子,https://blog.csdn.net/qq_39571197/article/details/87692484
使用到方法,resolveInject ()、defineReactive()。
4.5、initState()
#占
4.6、initProvide()
前面提到了,initInjections()在initProvide()之前。
这个函数很简单,就是执行以下,把数据挂载到this,不会调用defineReactive()使其变成响应式数据。
使用到方法,无。
5、接下来和开发与调试有关,查看性能
if (config.performance && mark) {
vm._name = formatComponentName(vm, false);
mark(endTag);
measure(("vue " + (vm._name) + " init"), startTag, endTag);
}
这个需要搭配 Vue Performance Devtool 浏览器扩展使用。
6、最后一步,显示到页面
if (vm.$options.el) {
vm.$mount(vm.$options.el);
}
$mount()是Vue.prototype上的一个方法;
6.1、对于new Vue()来说,如果不传入el属性,也可以从实例上手动调用$mount()方法
6.2、对于组件来说,在componentVNodeHooks中有个init()方法,会自动执行$mount()方法。
更多推荐
所有评论(0)