vue组件化原理

486 阅读2分钟

这是我参与11月更文挑战的第12天,活动详情查看:2021最后一次更文挑战

一、组件化机制

组件注册使用extend方法将配置转换为构造函数并添加到components选项

  • 全局声明Vue.component();
  • 局部声明components

组件实例创建及挂载

这是生成组件的渲染函数:

"with(this){return _c('div',{attrs:{"id":"demo"}},[
        //_c=createElement
 	_c('h1',[_v("虚拟DOM")]),_v(" "),//名字,组件
 	_c('p',[_v(_s(foo))]),_v(" "),
 	_c('comp') // 传入自定义组件
],1)}"

二、整体流程

new Vue()->$mount()->vm._render()->createElement()->createComponent()->vm._update->patch()->createElm->createComponent();

下面说下每个流程执行的工作内容:

1、创建根实例

首次_render()的时候,会拿到整棵树的VNode结构,其中自定义组件相关的主要是:

  • createComponent();src/core/vdom/create-component.js 执行组件vnode的创建,会先判断传入的标签类型,然后处理组件的属性(监听器,双向绑定等),然后安装组件的管理钩子和系统默认的钩子。
  • createComponent();src/core/vdom/patch.js 创建组件实例并进行挂载,vnode转换为真实DOM。

2、创建组件VNode

createElement执行虚拟dom的创建函数,由于是自定义组件,所以tab标签不会保留,直接创建。

createComponent 创建组件VNode,保留上一步得到的组件构造函数,参数props,事件等

3、创建组件实例

createElm根组件执行函数更新时,会递归创建子元素和子组件

首次执行_update时,patch会通过createElm创建根元素,也就是子元素的生成在这里。

createComponent组件实例的创建、挂载生成,插入到父元素的执行

if (isDef(i = i.hook) && isDef(i = i.init)) {
 	i(vnode, false /* hydrating */);
}
if (isDef(vnode.componentInstance)) {
        //实例创建完毕,初始化它的属性
	initComponent(vnode, insertedVnodeQueue);// 元素引⽤指定vnode.elm,元素属性创建等
	insert(parentElm, vnode.elm, refElm);// 插⼊到⽗元素DOM中
	if (isTrue(isReactivated)) {
		reactivateComponent(vnode, insertedVnodeQueue, parentElm, refElm)
	}
	return true;
}

三、总结

上面说的都是Vue2的组件化原理和流程,相对于vue1来说有更大的改变,在项目应用中有很强的适应性、跨平台和性能是里程碑的版本。

但是也有一些问题的存在:

  1. 数据响应式实现在性能上存在问题,对象和数组的处理上不一致引入了额外的API
  2. 没有充分利用预编译的优势,patch过程还有不少优化空间
  3. 响应式模块、渲染器模块都放在了核心模块中,后期扩展不太方便
  4. 选项式的编程模式在复杂业务的时候不利于维护