这是我参与11月更文挑战的第13天,活动详情查看:2021最后一次更文挑战
一、vue3源码架构
1、vue3初始化流程
<div id="app">
<h1>vue3初始化流程</h1>
</div>
<script src="../../dist/vue.global.js"></script>
<script>
const {createApp} = Vue;
createApp({}).mount('#app');
</script>
上面的代码中createAPP是如何创建vue实例的,创建vue的实例都做了什么?我们来看看内部的执行顺序:
2、执行流程
-
createApp();创建vue实例、扩展mount方法
-
createRenderer()/baseCreateRenderer();创建renderer对象,并对外暴露三个方法:render、hydrate、createApp。其中和hydrate的实际作用是createApp返回的vue实例对象。
-
createAppAPI(render, hydrate);返回生产vue实例的createApp函数
其中render的作用给vue实例的mount方法。这时候可以看出来component()、directive()、use()、mixin()这些方法都变成了实例方法,他们也会返回实例本身,成为链式调用。并且filter被移除了
createApp({})
.component('comp', { template: '<div>a comonent</div>' })
.directive('focus', { mounted(el) { el.focus() } })
.mount('#app');
-
mount(rootContainer: HostElement, isHydrate?: boolean);把createApp(rootComponent)中传⼊的根组件转换为vnode,然后渲染到宿主元素rootContainer中。
-
render(vnode, container);将vnode渲染到容器container上
-
patch(n1, n2, container);将传入的虚拟节点n1和n2进行对比,并转换成dom(初始化的时候n1是空的,所以操作之后会创建n1)
-
mount(rootContainer);执行根组件挂载,创建vnode,并把他render()出来
-
render();执行补丁函数patch();吧虚拟dom转换为真实dom
-
patch(n1, n2, container);根据n2的类型执行对应的函数,如果是根组件就会执行processComponent()方法
-
processComponent();执行组件挂载或更新,因为初始化n1是空的,所以挂载的时候会走mountComponent()
-
mountComponent();创建组件实例,执行setupComponent()设置数据状态,其中就包括setup选项的执行。
二、setup()的生效
因为vue3中可以使用composition-api,这个是写在setup()中的,下面说说它的执行过程:
1、根组件执行挂载mount()时,执行渲染函数render()获取组件的vnode,然后执行补丁函数patch()转换为真实dom,再根据组件类型判断是否走processComponent(),这里会实例化组件并处理setup选项
-
setupComponent();初始化props、slots和data
-
setupStatefulComponent(instance, isSSR);代理组件实例上下⽂,调⽤setup(),这时setup方法会收到两个参数:props和setupContext,可⽤于获取属性、插槽内容和派发事件。
-
handleSetupResult(instance, setupResult, isSSR);处理setup返回结果,如果是函数则作为组件的渲染函数,如果是对象则对其做响应化处理。
好啦这次主要说的vue3执行的过程,感谢阅读