最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Vue實(shí)例從初始化到掛載的完整流程

 更新時(shí)間:2025年12月25日 09:50:15   作者:全棧陳序員  
本文詳細(xì)解析了Vue實(shí)例從初始化到掛載的完整流程,首先通過new Vue()觸發(fā)_init方法進(jìn)行初始化,依次完成配置合并、生命周期/事件/渲染初始化,需要的朋友可以參考下

一、整體流程概覽

當(dāng)我們執(zhí)行 new Vue({ ... }) 時(shí),Vue 會(huì)經(jīng)歷 初始化 → 編譯模板 → 掛載 DOM 三個(gè)階段。整個(gè)過程由 _init 方法驅(qū)動(dòng),最終通過 $mount 完成視圖渲染。

核心路徑:
new Vue()_init()initState()$mount()mountComponent()_render()_update() → 真實(shí) DOM

二、詳細(xì)步驟解析

1. 構(gòu)造函數(shù)與_init初始化

源碼位置:src/core/instance/index.js

function Vue(options) {
  if (!(this instanceof Vue)) {
    warn('Vue is a constructor and should be called with the `new` keyword')
  }
  this._init(options)
}
  • 調(diào)用 _init 是整個(gè)實(shí)例化的起點(diǎn)。
  • 在此之前,Vue 原型上已通過 mixin 注入了各類方法:
    • initMixin → 定義 _init
    • stateMixin$set, $delete, $watch
    • eventsMixin$on, $emit
    • lifecycleMixin_update, $destroy
    • renderMixin_render

2._init中的關(guān)鍵操作

源碼位置:src/core/instance/init.js

Vue.prototype._init = function (options) {
  const vm = this;
  vm._uid = uid++;
  vm._isVue = true;

  // 合并配置(處理 mixins / extends)
  if (options && options._isComponent) {
    initInternalComponent(vm, options);
  } else {
    vm.$options = mergeOptions(
      resolveConstructorOptions(vm.constructor),
      options || {},
      vm
    );
  }

  // 初始化代理(開發(fā)環(huán)境)
  if (process.env.NODE_ENV !== 'production') {
    initProxy(vm);
  } else {
    vm._renderProxy = vm;
  }

  vm._self = vm;

  // 初始化生命周期、事件、渲染
  initLifecycle(vm);
  initEvents(vm);
  initRender(vm);

  callHook(vm, 'beforeCreate');

  // 初始化依賴注入(inject / provide)
  initInjections(vm);   // 在 data/props 之前
  initState(vm);        // 初始化 props, methods, data, computed, watch
  initProvide(vm);      // 在 data/props 之后

  callHook(vm, 'created');

  // 如果有 el,自動(dòng)掛載
  if (vm.$options.el) {
    vm.$mount(vm.$options.el);
  }
}

關(guān)鍵結(jié)論

  • beforeCreate 時(shí):data / props 尚未初始化,無(wú)法訪問;
  • created 時(shí):數(shù)據(jù)已響應(yīng)式化,但 DOM 還未生成,不能操作 $el;
  • 掛載由 $mount 觸發(fā)。

3. 數(shù)據(jù)初始化:initState與initData

源碼位置:src/core/instance/state.js

export function initState(vm) {
  vm._watchers = [];
  const opts = vm.$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);
}

function initData(vm) {
  let data = vm.$options.data;
  data = vm._data = typeof data === 'function'
    ? getData(data, vm)
    : data || {};

  // 校驗(yàn) data 為純對(duì)象
  if (!isPlainObject(data)) { /* warn */ }

  const keys = Object.keys(data);
  const props = vm.$options.props;
  const methods = vm.$options.methods;

  // 屬性名沖突檢查(data vs props/methods)
  for (let i = keys.length - 1; i >= 0; i--) {
    const key = keys[i];
    if (props && hasOwn(props, key)) { /* warn */ }
    else if (!isReserved(key)) {
      proxy(vm, '_data', key); // 通過 this.key 訪問 vm._data[key]
    }
  }

  // 響應(yīng)式化
  observe(data, true /* asRootData */);
}

重點(diǎn)

  • 組件中 data 必須是函數(shù)(避免多實(shí)例共享對(duì)象);
  • 通過 proxy 實(shí)現(xiàn) this.messagethis._data.message
  • 最終調(diào)用 observe 將 data 轉(zhuǎn)為響應(yīng)式(基于 Object.defineProperty)。

4. 掛載階段:$mount與模板編譯

源碼位置:src/platforms/web/entry-runtime-with-compiler.js

Vue.prototype.$mount = function (el, hydrating) {
  el = el && query(el);
  if (el === document.body || el === document.documentElement) {
    warn('Do not mount Vue to <html> or <body>');
    return this;
  }

  const options = this.$options;
  if (!options.render) {
    let template = options.template;
    if (template) {
      // 處理 string / element 類型的 template
    } else if (el) {
      template = getOuterHTML(el); // 從 el 提取 HTML
    }

    if (template) {
      // 編譯 template → render 函數(shù)
      const { render, staticRenderFns } = compileToFunctions(template, {}, this);
      options.render = render;
      options.staticRenderFns = staticRenderFns;
    }
  }

  // 調(diào)用真正的 mount
  return mount.call(this, el, hydrating);
}

關(guān)鍵點(diǎn)

  • 若無(wú) render 函數(shù),則嘗試從 templateel 提取模板;
  • 通過 compileToFunctions 將模板編譯為 render 函數(shù);
  • 編譯三步:HTML → AST → render 字符串 → render 函數(shù)。

5. 渲染組件:mountComponent

源碼位置:src/core/instance/lifecycle.js

export function mountComponent(vm, el, hydrating) {
  vm.$el = el;

  if (!vm.$options.render) {
    vm.$options.render = createEmptyVNode;
    // 警告:運(yùn)行時(shí)版本缺少編譯器
  }

  callHook(vm, 'beforeMount');

  // 定義更新函數(shù)
  let updateComponent = () => {
    vm._update(vm._render(), hydrating);
  };

  // 創(chuàng)建渲染 Watcher(核心!)
  new Watcher(vm, updateComponent, noop, {
    before() {
      if (vm._isMounted && !vm._isDestroyed) {
        callHook(vm, 'beforeUpdate');
      }
    }
  }, true /* isRenderWatcher */);

  hydrating = false;

  if (vm.$vnode == null) {
    vm._isMounted = true;
    callHook(vm, 'mounted');
  }

  return vm;
}

? 核心機(jī)制

  • 創(chuàng)建一個(gè) 渲染 Watcher,監(jiān)聽響應(yīng)式數(shù)據(jù)變化;
  • 初次執(zhí)行 updateComponent → 觸發(fā)首次渲染;
  • 數(shù)據(jù)變更時(shí),自動(dòng)觸發(fā) beforeUpdate → 重新 _render_update。

6. 生成 VNode 與更新 DOM

_render:生成虛擬 DOM

Vue.prototype._render = function () {
  const { render } = this.$options;
  let vnode;
  try {
    vnode = render.call(this._renderProxy, this.$createElement);
  } catch (e) { /* error handling */ }
  // 校驗(yàn) vnode 合法性
  return vnode;
}

_update:將 VNode 轉(zhuǎn)為真實(shí) DOM

Vue.prototype._update = function (vnode, hydrating) {
  const vm = this;
  const prevVnode = vm._vnode;
  vm._vnode = vnode;

  if (!prevVnode) {
    // 初次掛載
    vm.$el = vm.__patch__(vm.$el, vnode, hydrating, false);
  } else {
    // 更新
    vm.$el = vm.__patch__(prevVnode, vnode);
  }
}
  • __patch__ 是平臺(tái)相關(guān)方法(Web 端為 patch 函數(shù)),負(fù)責(zé) VNode diff + DOM 操作。

三、總結(jié):掛載全過程

階段關(guān)鍵動(dòng)作生命周期鉤子
初始化合并配置、初始化 props/data/methods/watchbeforeCreatecreated
編譯template → AST → render 函數(shù)
掛載創(chuàng)建渲染 Watcher,首次執(zhí)行 _render + _updatebeforeMountmounted
更新數(shù)據(jù)變化 → 觸發(fā) Watcher → 重新渲染beforeUpdateupdated

一句話概括
Vue 實(shí)例掛載的本質(zhì)是——將響應(yīng)式數(shù)據(jù)通過 render 函數(shù)生成 VNode,再通過 patch 算法高效更新到真實(shí) DOM 上,整個(gè)過程由一個(gè) 渲染 Watcher 驅(qū)動(dòng)。

以上就是Vue實(shí)例從初始化到掛載的完整流程的詳細(xì)內(nèi)容,更多關(guān)于Vue實(shí)例掛載流程的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Vue2?響應(yīng)式系統(tǒng)之深度響應(yīng)

    Vue2?響應(yīng)式系統(tǒng)之深度響應(yīng)

    這篇文章主要介紹了Vue2?響應(yīng)式系統(tǒng)之深度響應(yīng),文章基于Vue2?響應(yīng)式系統(tǒng)的相關(guān)資料展開對(duì)Vue2?深度響應(yīng)的介紹,需要的小伙伴可以參考一下
    2022-04-04
  • vue-dplayer視頻播放器組件的使用詳解

    vue-dplayer視頻播放器組件的使用詳解

    Vue-DPlayer是一個(gè)易于使用、高性能的基于Vue.js的視頻播放器組件,這篇文章將為大家詳細(xì)介紹一下vue-dplayer視頻播放器組件的安裝與使用,需要的小伙伴可以參考下
    2023-09-09
  • Ant Design Vue table中列超長(zhǎng)顯示...并加提示語(yǔ)的實(shí)例

    Ant Design Vue table中列超長(zhǎng)顯示...并加提示語(yǔ)的實(shí)例

    這篇文章主要介紹了Ant Design Vue table中列超長(zhǎng)顯示...并加提示語(yǔ)的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來(lái)看看吧
    2020-10-10
  • vue實(shí)現(xiàn)pc端拍照上傳功能

    vue實(shí)現(xiàn)pc端拍照上傳功能

    這篇文章主要為大家詳細(xì)介紹了vue實(shí)現(xiàn)pc端拍照上傳功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-09-09
  • vue中LocalStorage與SessionStorage的區(qū)別與用法

    vue中LocalStorage與SessionStorage的區(qū)別與用法

    本文主要介紹了LocalStorage和SessionStorage。LocalStorage和SessionStorage是兩種存儲(chǔ)方式,本文詳細(xì)的介紹一下區(qū)別以及用法,感興趣的可以了解一下
    2021-09-09
  • vue通過點(diǎn)擊事件讀取音頻文件的方法

    vue通過點(diǎn)擊事件讀取音頻文件的方法

    最近做項(xiàng)目遇到這樣的一個(gè)需求,通過select元素來(lái)選擇音頻文件的名稱,點(diǎn)擊按鈕可以進(jìn)行試聽。接下來(lái)通過本文給大家介紹vue項(xiàng)目中通過點(diǎn)擊事件讀取音頻文件的方法,需要的朋友可以參考下
    2018-05-05
  • 使用el-upload實(shí)現(xiàn)文件上傳方式(包括預(yù)覽,下載)

    使用el-upload實(shí)現(xiàn)文件上傳方式(包括預(yù)覽,下載)

    該文章介紹了兩種文件上傳、預(yù)覽和下載的方法,分別是通過卡片形式和按鈕形式,卡片形式中的下載和預(yù)覽功能尚未完善,父組件使用了el-upload組件,可以實(shí)現(xiàn)新增、編輯和查看文件的功能
    2025-11-11
  • vue瀑布流組件實(shí)現(xiàn)上拉加載更多

    vue瀑布流組件實(shí)現(xiàn)上拉加載更多

    這篇文章主要為大家詳細(xì)介紹了vue瀑布流組件實(shí)現(xiàn)上拉加載更多,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-03-03
  • 基于vue2.0的活動(dòng)倒計(jì)時(shí)組件countdown(附源碼下載)

    基于vue2.0的活動(dòng)倒計(jì)時(shí)組件countdown(附源碼下載)

    這是一款基于vue2.0的活動(dòng)倒計(jì)時(shí)組件,可以使用服務(wù)端時(shí)間作為當(dāng)前時(shí)間,在倒計(jì)時(shí)開始和結(jié)束時(shí)可以自定義回調(diào)函數(shù)。這篇文章主要介紹了基于vue2.0的活動(dòng)倒計(jì)時(shí)組件countdown,需要的朋友可以參考下
    2018-10-10
  • Vue3中路由跳轉(zhuǎn)優(yōu)化技巧分享

    Vue3中路由跳轉(zhuǎn)優(yōu)化技巧分享

    這篇文章主要為大家詳細(xì)介紹了Vue3中路由跳轉(zhuǎn)的相關(guān)優(yōu)化技巧,文中的示例代碼講解詳細(xì),具有一定的借鑒價(jià)值,有需要的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2025-07-07

最新評(píng)論

峨山| 美姑县| 隆德县| 五家渠市| 刚察县| 济源市| 安仁县| 永登县| 革吉县| 崇州市| 桃江县| 盱眙县| 晋城| 皋兰县| 白玉县| 武夷山市| 四平市| 津南区| 丹棱县| 南安市| 酉阳| 炎陵县| 喀喇沁旗| 类乌齐县| 武陟县| 白城市| 犍为县| 多伦县| 金阳县| 阜宁县| 马山县| 吉林省| 泸州市| 阳朔县| 金昌市| 南靖县| 灵山县| 新闻| 宿松县| 潮安县| 富平县|