2026/4/18 9:09:04
网站建设
项目流程
常州 微网站,展会网站模板,培训类网站模板,WordPress网站转APP插件整体流程
完整的创建与渲染流程可以分成这些阶段#xff1a;
创建 App 实例创建根组件实例设置响应式状态创建渲染器#xff08;Renderer#xff09;挂载 Mountvnode - DOM 渲染数据变更触发更新重新渲染 / diff / patch
流程图大致如下#xff1a;
createApp() ───…整体流程完整的创建与渲染流程可以分成这些阶段创建 App 实例创建根组件实例设置响应式状态创建渲染器Renderer挂载 Mountvnode - DOM 渲染数据变更触发更新重新渲染 / diff / patch流程图大致如下createApp() ─── app.mount(#app) │ │ ▼ ▼ createRootComponent createRenderer │ │ ▼ ▼ setup() / render() render(vnode) - patch │ │ ▼ ▼ effect(fn) ──── scheduler - patch updates1、createApp 初始化Vue 应用的入口通常是createApp(App).mount(#app)从源码看 createApp// packages/runtime-core/src/apiCreateApp.ts export function createAppAPI(render) { return function createApp(rootComponent, rootProps null) { const app { _component: rootComponent, _props: rootProps, _container: null, _context: createAppContext() } const proxy (app._instance { app }) // register global APIs // ... return { mount(container) { const vnode createVNode(rootComponent, rootProps) app._container container render(vnode, container) }, unmount() { /* ... */ } } } }关键点createAppAPI(render)生成 createApp 函数app 内保存_component、上下文_contextapp.mount调用render(vnode, container)render由平台渲染器注入在 web 下是 DOM 渲染器。2、createVNode 创建虚拟节点VNode在 mount 前会创建一个虚拟节点function createVNode(type, props, children) { const vnode { type, props, children, shapeFlag: getShapeFlag(type), el: null, key: props props.key } return vnode }vnode是渲染的基础单元shapeFlag用来快速判断 vnode 类型是内部性能优化。3、渲染器 Renderer 初始化Vue3 是平台无关的runtime-core真正依赖 DOM 的是在runtime-dom中。创建 Rendererexport const renderer createRenderer({ createElement: hostCreateElement, patchProp: hostPatchProp, insert: hostInsert, remove: hostRemove, setElementText: hostSetElementText })createRenderer返回了我们前面在 createApp 中使用的render(vnode, container)函数。4、render patch核心渲染入口function render(vnode, container) { patch(null, vnode, container, null, null) }patch 是渲染补丁函数function patch(n1, n2, container, parentComponent, anchor) { const { type, shapeFlag } n2 if (shapeFlag ShapeFlags.ELEMENT) { processElement() } else if (shapeFlag ShapeFlags.STATEFUL_COMPONENT) { processComponent(...) } }简化为如果是DOM 元素 vnode→ 挂载/更新如果是组件 vnode→ 创建组件实例、挂载、渲染子树5、组件实例创建当渲染组件时function processComponent(n1, n2, container, parentComponent, anchor) { mountComponent(n2, container, parentComponent, anchor) } function mountComponent(vnode, container, parentComponent, anchor) { const instance createComponentInstance(vnode, parentComponent) setupComponent(instance) setupRenderEffect(instance, container, anchor) }processComponent 处理组件mountComponent 挂载组件createComponentInstance 创建组件实例setupComponent 创建组件对象createComponentInstancefunction createComponentInstance(vnode, parent) { const instance { vnode, parent, proxy: null, ctx: {}, props: {}, attrs: {}, slots: {}, setupState: {}, isMounted: false, subTree: null } return instance }实例保存基础信息还没运行 setup。6、 setupComponent初始化组件function setupComponent(instance) { initProps(instance, vnode.props) initSlots(instance, vnode.children) setupStatefulComponent(instance) }内部会执行const { setup } Component if (setup) { const setupResult setup(props, ctx) handleSetupResult(instance, setupResult) }setup 返回值返回对象 → 作为响应式状态 state返回函数 → render 函数最终让组件拥有instance.render。7、创建响应式状态Vue3 的响应式来自reactivity包const state reactive({ count: 0 })底层是Proxy拦截 getter/settergetter收集依赖setter触发依赖更新依赖管理核心是 effect / track / trigger。8、 setupRenderEffect 与首次渲染创建渲染器副作用并调度组件挂载和异步更新function setupRenderEffect(instance, container, anchor) { instance.update effect(function componentEffect() { if (!instance.isMounted) { const subTree (instance.subTree instance.render.call(proxy)) patch(null, subTree, container, instance, anchor) instance.isMounted true } else { // 更新更新逻辑 } }, { scheduler: queueJob }) }这里创建一个响应式 effect第一次执行 render 得到 subTreepatch 子树到 DOMeffectscheduler实现异步更新。9、vnode- 真实 DOMDOM mount当 patch 到真正的 DOM 时走的是 element 分支function processElement(...) { if (!n1) { mountElement(vnode, container) } else { patchElement(n1, n2) } }mountElementfunction mountElement(vnode, container) { const el (vnode.el hostCreateElement(vnode.type)) // props for (key in props) { hostPatchProp(el, key, null, props[key]) } // children if (typeof children string) { hostSetElementText(el, children) } else { children.forEach(c patch(null, c, el)) } hostInsert(el, container) }10、更新 Diff 算法当响应式状态改变state.count触发 setter →trigger将 effect 放入更新队列异步执行 scheduler调用 instance.update 再次 patch更新阶段patchElement(n1, n2)核心逻辑props diffchildren diffunkeyed/keyed diff算法最小化移动具体见patchChildren和patchKeyedChildren。整体核心对象关系架构App └─ vnode(root) └─ ComponentInstance ├─ props / slots ├─ setupState └─ render() - subTree └─ vnode tree └─ DOM nodes响应式依赖结构reactive state ├─ effects[] └─ track - effect └─ scheduler - patch