万泉河网站建设,做物流网站的多少钱,建设网站北京,淮北住房和城乡建设局门户网站一、整体流程概览
当我们执行 new Vue({ ... }) 时#xff0c;Vue 会经历 初始化 → 编译模板 → 挂载 DOM 三个阶段。整个过程由 _init 方法驱动#xff0c;最终通过 $mount 完成视图渲染。 核心路径#xff1a; new Vue() → _init() → initState() → $mount() → moun…一、整体流程概览当我们执行new Vue({ ... })时Vue 会经历初始化 → 编译模板 → 挂载 DOM三个阶段。整个过程由_init方法驱动最终通过$mount完成视图渲染。核心路径new Vue()→_init()→initState()→$mount()→mountComponent()→_render()→_update()→ 真实 DOM二、详细步骤解析1. 构造函数与_init初始化源码位置src/core/instance/index.jsfunctionVue(options){if(!(thisinstanceofVue)){warn(Vue is a constructor and should be called with the new keyword)}this._init(options)}调用_init是整个实例化的起点。在此之前Vue 原型上已通过 mixin 注入了各类方法initMixin→ 定义_initstateMixin→$set,$delete,$watcheventsMixin→$on,$emitlifecycleMixin→_update,$destroyrenderMixin→_render2._init中的关键操作源码位置src/core/instance/init.jsVue.prototype._initfunction(options){constvmthis;vm._uiduid;vm._isVuetrue;// 合并配置处理 mixins / extendsif(optionsoptions._isComponent){initInternalComponent(vm,options);}else{vm.$optionsmergeOptions(resolveConstructorOptions(vm.constructor),options||{},vm);}// 初始化代理开发环境if(process.env.NODE_ENV!production){initProxy(vm);}else{vm._renderProxyvm;}vm._selfvm;// 初始化生命周期、事件、渲染initLifecycle(vm);initEvents(vm);initRender(vm);callHook(vm,beforeCreate);// 初始化依赖注入inject / provideinitInjections(vm);// 在 data/props 之前initState(vm);// 初始化 props, methods, data, computed, watchinitProvide(vm);// 在 data/props 之后callHook(vm,created);// 如果有 el自动挂载if(vm.$options.el){vm.$mount(vm.$options.el);}}✅关键结论beforeCreate时data / props 尚未初始化无法访问created时数据已响应式化但DOM 还未生成不能操作$el挂载由$mount触发。3. 数据初始化initState与initData源码位置src/core/instance/state.jsexportfunctioninitState(vm){vm._watchers[];constoptsvm.$options;if(opts.props)initProps(vm,opts.props);if(opts.methods)initMethods(vm,opts.methods);if(opts.data)initData(vm);if(opts.computed)initComputed(vm,opts.computed);if(opts.watch)initWatch(vm,opts.watch);}functioninitData(vm){letdatavm.$options.data;datavm._datatypeofdatafunction?getData(data,vm):data||{};// 校验 data 为纯对象if(!isPlainObject(data)){/* warn */}constkeysObject.keys(data);constpropsvm.$options.props;constmethodsvm.$options.methods;// 属性名冲突检查data vs props/methodsfor(letikeys.length-1;i0;i--){constkeykeys[i];if(propshasOwn(props,key)){/* warn */}elseif(!isReserved(key)){proxy(vm,_data,key);// 通过 this.key 访问 vm._data[key]}}// 响应式化observe(data,true/* asRootData */);}✅重点组件中data必须是函数避免多实例共享对象通过proxy实现this.message→this._data.message最终调用observe将 data 转为响应式基于Object.defineProperty。4. 挂载阶段$mount与模板编译源码位置src/platforms/web/entry-runtime-with-compiler.jsVue.prototype.$mountfunction(el,hydrating){elelquery(el);if(eldocument.body||eldocument.documentElement){warn(Do not mount Vue to html or body);returnthis;}constoptionsthis.$options;if(!options.render){lettemplateoptions.template;if(template){// 处理 string / element 类型的 template}elseif(el){templategetOuterHTML(el);// 从 el 提取 HTML}if(template){// 编译 template → render 函数const{render,staticRenderFns}compileToFunctions(template,{},this);options.renderrender;options.staticRenderFnsstaticRenderFns;}}// 调用真正的 mountreturnmount.call(this,el,hydrating);}✅关键点若无render函数则尝试从template或el提取模板通过compileToFunctions将模板编译为render函数编译三步HTML → AST → render 字符串 → render 函数。5. 渲染组件mountComponent源码位置src/core/instance/lifecycle.jsexportfunctionmountComponent(vm,el,hydrating){vm.$elel;if(!vm.$options.render){vm.$options.rendercreateEmptyVNode;// 警告运行时版本缺少编译器}callHook(vm,beforeMount);// 定义更新函数letupdateComponent(){vm._update(vm._render(),hydrating);};// 创建渲染 Watcher核心newWatcher(vm,updateComponent,noop,{before(){if(vm._isMounted!vm._isDestroyed){callHook(vm,beforeUpdate);}}},true/* isRenderWatcher */);hydratingfalse;if(vm.$vnodenull){vm._isMountedtrue;callHook(vm,mounted);}returnvm;}✅核心机制创建一个渲染 Watcher监听响应式数据变化初次执行updateComponent→ 触发首次渲染数据变更时自动触发beforeUpdate→ 重新_render→_update。6. 生成 VNode 与更新 DOM_render生成虚拟 DOMVue.prototype._renderfunction(){const{render}this.$options;letvnode;try{vnoderender.call(this._renderProxy,this.$createElement);}catch(e){/* error handling */}// 校验 vnode 合法性returnvnode;}_update将 VNode 转为真实 DOMVue.prototype._updatefunction(vnode,hydrating){constvmthis;constprevVnodevm._vnode;vm._vnodevnode;if(!prevVnode){// 初次挂载vm.$elvm.__patch__(vm.$el,vnode,hydrating,false);}else{// 更新vm.$elvm.__patch__(prevVnode,vnode);}}__patch__是平台相关方法Web 端为patch函数负责VNode diff DOM 操作。三、总结挂载全过程阶段关键动作生命周期钩子初始化合并配置、初始化 props/data/methods/watchbeforeCreate→created编译template → AST → render 函数—挂载创建渲染 Watcher首次执行_render_updatebeforeMount→mounted更新数据变化 → 触发 Watcher → 重新渲染beforeUpdate→updated一句话概括Vue 实例挂载的本质是——将响应式数据通过 render 函数生成 VNode再通过 patch 算法高效更新到真实 DOM 上整个过程由一个渲染 Watcher驱动。参考文献博客园Vue 实例化过程Vue 2.x 源码 GitHubVue 3 中文文档对比参考