组件是如何创建和挂载的?它和父组件的创建和挂载是个怎样的过程?组件的生命周期是怎样的?
我们平时使用组件都是先进行组件注册,组件注册有两种方式,一种是注册全局组件使用Vue的全局静态方法Vue.component进行注册,还有一种就是组件内部利用components属性进行注册。注册之后我们就会在模板里进行声明使用,模板里声明使用的组件最后回被编译返回一个渲染函数rander。在未来某个时刻执行渲染函数rander得到虚拟DOM(vnode),再由vnode渲染成真实DOM进行挂载。
步骤:
-
注册组件
Vue.component(id, comp)
components
-
声明组件
<template>
<comp></comp>
</tamplate>
-
编译得到渲染函数
rende [template => render()] -
某个时刻(挂载
$mount=>mountComponent)执行渲染函数render() => vnode -
patch
模板里的组件编译后是什么样的
<div id="app">
<h1>coboy</h1>
<comp></comp>
</div>
<script src="https://unpkg.com/vue@2.6.14/dist/vue.js"></script>
<script>
Vue.component('Comp', {
template: '<div>this a comp</div>'
})
const app = new Vue({
el: '#app'
})
console.log('render:', app.$options.render)
</script>
打印出来的渲染函数
//render:
ƒ anonymous(
) {
with(this){
return _c('div',{attrs:{"id":"app"}},[
_c('h1',[
_v("coboy")]),
_v(" "),
_c('comp')],1)
}
}
得到的渲染函数是一个匿名函数
with(this)限定了函数里面的this都是执行当前组件的实例
我们发现渲染函数render在处理html保留标签和组件标签都是使用_c这个函数进行处理
这些下划线的函数在core\instance\render-helpers\index.js里。但_c却在core\instance\render.js里的initRender函数中定义的。其中_c是Vue内部使用的,用于编译器生成的render函数,用户编写的render函数使用的是$createElement(h函数) 。
我们发现处理原生的HTML元素和自定义组件都是使用同一个函数_c,然后在createElement里进行判断如果是HTML保留标签就创建标签,否则就进行组件实例创建。
怎么进行组件注册?
先进进行组件定义再组件实例化,组件实例化之后,组件实例里有组件挂载函数$mount
// core/global-api/index
// 元件的注册
initAssetRegisters(Vue)
// core/global-api/assets
function initAssetRegisters()
// 如果是对象,说明传入是组件配置,此时需要做转换:对象=》组件构造函数
if (type === 'component' && isPlainObject(definition)) {}
Vue.extend()
// 构造函数的获取:Vue.extend(obj) => VueComponet
definition = this.options._base.extend(definition)
// 注册到全局配置项中
// options.components['comp'] = Ctor
// 全局注册就是添加到系统选项中,以后所有组件初始化的时候,会有一个合并的动作,这样所有的这些全局组件就放入了当前组件的components选项中
this.options[type + 's'][id] = definition
通过传入组件配置获取组件构造函数VueComponet之后,可以通过new VueComponent得到组件实例,然后执行组件实例的渲染函数得到vnode,再通过组件实例的$mount方法进行挂载,这个过程和根组件的挂载过程是一样的。
自定义组件创建和挂载的时机
在父组件创建后,未挂载前。在patch()中创建和挂载。
父子组件的生命周期关系
创建过程:先父后子。挂载过程:先子后父。 parent.created => parent.beforeMounted => child.created => child.beforeMount => child.mounted… => parent.mounted…