Vue-组件的初始化和渲染过程
组件(Component
)是Vue
一个重要的功能。一般用于包装可重用代码,或者是定义高级组件。对于小型项目,(可能)会增强代码的结构性,但是并非必须。对于稍大型的项目,它则是模块化的基础,也是代码拆分常用的形式。
组件有很多内容,比如组件消息传递、数据传递、slot
、异步组件等等,作为一个有品味的博主,以上内容本篇统统不涉及。本篇只从一个注册+创建角度说一下组件是怎么一步一步放到页面上的。
基础示例代码(来自Vue
官方文档)
1 2 3 |
<div id="example"> <my-component></my-component> </div> |
1 2 3 4 5 6 7 8 |
// 注册 Vue.component('my-component', { template: '<div>A custom component!</div>' }) // 创建根实例 new Vue({ el: '#example' }) |
整体来说,组件使用需要经过两个步骤:声明和实例化。声明即把组件的显式声明内容,处理为配置项,挂载到实例上。接着根据模板解析的流程,在不同的地方根据配置初始化为一个一个的组件实例。
组件声明
组件通常使用全局注册或者局部注册,二者没有本质区别(吧)。我们从全局注册角度说一下
1 2 3 |
Vue.component(name, definition) // name为'my-component',definition是配置项 -Sub = Vue.extend(definition) -Vue.options['components']['my-component'] = Sub |
组件渲染(实例化)
上篇(Vue-初始化和渲染过程)讲到,渲染是从initRender
开始的,当执行到createElement
时,会分为不同类型的节点来处理。这里对此操作展开叙述。
重述一下前面的流程
1 2 3 4 |
-initRender -Vue._mount -vm._render -createElm // 生成VNode节点 |
createElm
这里会分为组件、浏览器tag
、comment
、文本分别处理对应的element
。Vue挂载的根组件只能为组件或者tag
,不能为comment
或者文本。
另外,在Vue
模板解析(initRender
)时,不区分是否为组件的。所有元素都在createElement
函数内处理,最后都会生成一个模板函数
1 |
_h(tagName, {...}) |
实际区分在从组件的父节点调用createElm
,来生成VNode
的时候。为不打断流程,组件VNode
相关放在最后说。
如果是组件,会进行组件初始化(init
)流程:
init
负责会按层次处理好子节点
1 2 3 |
-vnode.child = createComponentInstanceForVnode -vnode.child.$mount =Vue.prototype._mount |
按照最外层vm实例初始化的步骤,再走一边组件的初始化
1 2 3 |
vm._render // 这里vm是vnode.child,即VueComponent实例 -vm._update -vm.$el = vm.__patch__ |
基本流程图如下
这是一个递归调用,直到节点不为组件(浏览器tag
、comments
、text
三种),返回创建的基础elm元素。当节点的children
为空时,会返回父级创建的浏览器tag
元素。
生成的元素被放入vnode.elm
中。
组件VNode
相关
1 2 3 |
-createElm -createElement -createComponent |
如果是组件,会先返回一个占位vnode
,当将组件的所有子节点按层次处理完之后,再把child
(此时已经为可用的tag
)赋值给vnode.elm
,这样这个组件就可以使用了。
这个占位vnode
,除默认字段外,只设置了tag、data、context、componentOptions
1 2 3 4 5 6 7 8 |
// tag ("vue-component-" + (Ctor.cid) + (name ? ("-" + name) : '')) // 如:vue-component-1-button-counter // data {hook: init, insert, prepatch, destroy} // 组件操作入口 // componentOptions { Ctor: Ctor, propsData: propsData, listeners: listeners, tag: tag, children: children } |
createElement
判断定义了data.hook
函数,就执行组件实例初始化和挂载,这是个基础流程,和Vue
初始化的一致。
看不懂(学不进去)…直接照搬用
@zwwooooo 只是个笔记啦,也没啥实用价值
vuejs 依赖收集这块的想法真的很巧妙
@牧风 嗯,想法很棒,setProperty用的也很6
Vue觉得比react要简单,双向绑定,唉,react学起来感觉好烦
@VPS234 感觉简单是因为语法糖比较多,用起来很顺手。但是也经常遇到坑,比如在模板里写了函数,却忘记放methods里加调用;又或者看别人代码,需要在模板和js里对比是data、methods还是computed
非技术的路过。
看到一个人成为大师的过程。
@郑永
看人家的东西看不出成果,还是得自己“创作”
现在的前端都不懂了。。就觉得好厉害的样子
@黄小蚊 功能越多,坑也越多,还是指数级