摘要:寫文章不容易,點個贊唄兄弟專注源碼分享,文章分為白話版和源碼版,白話版助于理解工作原理,源碼版助于了解內部詳情,讓我們一起學習吧研究基于版本如果你覺得排版難看,請點擊下面鏈接或者拉到下面關注公眾號也可以吧原理源碼版之掛載組件由這篇文章從模
</>復制代碼
寫文章不容易,點個贊唄兄弟
專注 Vue 源碼分享,文章分為白話版和 源碼版,白話版助于理解工作原理,源碼版助于了解內部詳情,讓我們一起學習吧
研究基于 Vue版本 【2.5.17】
如果你覺得排版難看,請點擊 下面鏈接 或者 拉到 下面關注公眾號也可以吧
【Vue原理】Component - 源碼版 之 掛載組件DOM
由這篇文章 從模板到DOM的簡要流程
我們知道,在生成 VNode 之后,下一步就是根據 VNode 生成DOM然后掛載了
在本文開始之前你可以先看 Component - 白話版 先整體了解下component
現在開始我們的正文
上一篇文章 Component - 創建組件VNode ,我們已經說到了 【頁面模板解析成 VNode 樹】的步驟
那今天就就到了 【頁面VNode生成DOM掛載】 了
等等,今天說的不是 Component 掛載DOM 嗎?跟頁面Vnode 有什么關系??是啊,component 的掛載肯定是跟著父頁面的啊,你自己掛?自掛東南枝嗎?
好了,廢話不說,馬上開始
前言預告這篇 從模板到DOM的簡要流程 已經說過下面的步驟
1vm._render 執行得到 頁面VNode
2vm._update 拿到 頁面VNode ,會開始 patch,不斷比對 【舊VNode 和 剛拿到的新VNode】
對比完之后,會調用一個 createElm 的方法去創建DOM,然后插入頁面
那現在,我們就從 createElm 這個方法突破,前面的流程跟本內容無關,一律略過
</>復制代碼
function createElm(vnode, parentElm, refElm) {
// 組件需要特殊處理
if (createComponent(vnode, parentElm, refElm)) return
...正常的標簽,需要不斷遞歸子節點調用 createElm ,
然后生成DOM,并插入到父節點
}
createElm 的作用就是根據 標簽名創建 DOM 節點,然后掛載到父節點中,其中參數如下
</>復制代碼
parentElm == 父DOM 節點
refElm == 兄弟DOM節點,你插入父節點,可能也要知道插在誰附近不是嗎,不能亂插的
然后很明顯,createElm 每次掉要給你都會調用 【createComponent】 去檢測這個標簽是否是組件
如果是組件,就會去創建這個組件的實例,并且 返回 true,從而不用去執行 createElm 下面的部分
調用組件生命鉤子看下 createComponent
</>復制代碼
function createComponent(vnode, parentElm, refElm) {
var data = vnode.data;
var hook = i.hook;
var init = i.init;
// 調用子組件的 init 方法, init 方法就是 Vue.prototype._init
if (init) {
// 創建子組件的 vm 實例
init(vnode, parentElm, refElm);
// 如果存在組件實例,就是上一步創建成功了
if (vnode.componentInstance) {
return true
}
}
}
有沒有好奇 vnode.data.hook.init 是什么嗎?
他是每個組件,都會被 【注冊進外殼節點的鉤子函數】,沒錯,就是下面的鉤子,源碼
什么是組件生命鉤子沒錯,這就是那個鉤子的源碼
</>復制代碼
var componentVNodeHooks = {
init(vnode, parentElm, refElm) {
var vm=
vnode.componentInstance =
createComponentInstanceForVnode(
vnode,activeInstance,
parentElm, refElm
);
// 因為 在 Vue.prototype._init 中 ,只有 $options存在 el,才會掛載 dom
// 這里手動掛載組件
vm.$mount(vnode.elm);
}
...
}
那么,鉤子是什么時候注冊的呢?
嗯,在上一篇文章,【創建組件外殼VNode的過程中】,然后保存到了外殼節點的 data 上
</>復制代碼
function createComponent(
Ctor, data, context,
children, tag
) {
...創建組件構造函數
var hooks = data.hook || (data.hook = {});
data.hook.init = componentVNodeHooks.init
...創建組件VNode,并保存組件構造函數 和鉤子 等到 vnode 中
}
打印一下實際VNode,沒錯,有很多鉤子,但是現在只說 init
來吧,仔細看那個init 鉤子源碼,你可以看到調用了一個方法
createComponentInstanceForVnode
開始深入探索它.........
創建組件實例createComponentInstanceForVnode 函數作用就是給 component 【增加定制options】 + 【調用組件構造函數】
</>復制代碼
function createComponentInstanceForVnode(
vnode, parent,
parentElm, refElm
) {
// 增加 component 特有options
var options = {
_isComponent: true,
parent: parent, // 父實例
_parentVnode: vnode, // 外殼節點
_parentElm: parentElm , // 父DOM
_refElm: refElm // 兄弟DOM
};
// vnode.components.Ctor 就是 構造函數 ,里面會調用 Vue.prototype._init
return new vnode.componentOptions.Ctor(options)
}
vnode.componentOptions.Ctor 就是 構造函數,就是下面這個,上篇文章 Component - 創建組件VNode 時保存在外殼節點的
</>復制代碼
function VueComponent(options) {
this._init(options);
}
new 了之后,自然而然,走到了 _init 方法,在 init 方法中,有一個特殊照顧 component 的方法,專門給 component 實例設置options
"這一步跟 掛載組件DOM 沒什么關聯,想去掉的,但是想想還是先保留下來,完整整個流程"
</>復制代碼
Vue.prototype._init = function(options) {
if (如果是組件) {
initInternalComponent(vm, options);
}
}
組件初始化 initInteralComponent
</>復制代碼
function initInternalComponent(vm, options) {
// 這個options 就是在創建構造函數時,合并的 options,全局選項和組件設置選項
var opts = vm.$options = Object.create(vm.constructor.options);
// 保存父節點,外殼節點,兄弟節點等
var parentVnode = options._parentVnode; // _parentVnode 是外殼節點
opts.parent = options.parent; // options.parent 是 父實例
opts._parentVnode = parentVnode;
opts._parentElm = options._parentElm;
opts._refElm = options._refElm;
// 保存父組件給子組件關聯的數據
var vnodeComponentOptions = parentVnode.componentOptions;
opts.propsData = vnodeComponentOptions.propsData;
opts._parentListeners = vnodeComponentOptions.listeners;
opts._renderChildren = vnodeComponentOptions.children;
opts._componentTag = vnodeComponentOptions.tag;
// 保存渲染函數
if (options.render) {
opts.render = options.render;
opts.staticRenderFns = options.staticRenderFns;
}
}
這個時候, init 的過程就完成了
下一步就是到了 mount 過程
組件解析模板并掛載可以再回看下 「componentVNodeHooks.init 」 那個鉤子源碼
在創建組件實例成功之后,會手動調用實例 vm.$mount 進行掛載,就是這句代碼完成的功能
然而,掛載的步驟,就是正常標簽掛載的步驟了
詳情可以查看 從模板到DOM的簡要流程
的 mount 過程,是一毛一樣的,就不多說了
1、父頁面已經拿到了 VNode,其中會調用 createElm 根據 VNode 生成DOM,進行掛載
2、不斷的遞歸遍歷子節點,使用 createComponent 判斷標簽是否是組件
3、遇到組件,拿到組件外殼VNode 的data(data 保存有父組件給子組件的,事件,props,構造函數,鉤子)
4、從 data 中拿到 hook,hook 中拿到 init 鉤子,并執行 init 鉤子
5、init 鉤子中,調用 createComponentInstanceForVnode 調用組件構造函數,并返回組件
6、init 鉤子中,使用上一步返回的實例,手動調用 vm.$mount 進行組件內部模板解析渲染,并掛載
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/105470.html
摘要:寫文章不容易,點個贊唄兄弟專注源碼分享,文章分為白話版和源碼版,白話版助于理解工作原理,源碼版助于了解內部詳情,讓我們一起學習吧研究基于版本如果你覺得排版難看,請點擊下面鏈接或者拉到下面關注公眾號也可以吧原理源碼版之創建組件今天就要開啟我 寫文章不容易,點個贊唄兄弟專注 Vue 源碼分享,文章分為白話版和 源碼版,白話版助于理解工作原理,源碼版助于了解內部詳情,讓我們一起學習吧研究基于...
摘要:寫文章不容易,點個贊唄兄弟專注源碼分享,文章分為白話版和源碼版,白話版助于理解工作原理,源碼版助于了解內部詳情,讓我們一起學習吧研究基于版本如果你覺得排版難看,請點擊下面鏈接或者拉到下面關注公眾號也可以吧原理白話版從模板上使用到掛載到頁面 寫文章不容易,點個贊唄兄弟專注 Vue 源碼分享,文章分為白話版和 源碼版,白話版助于理解工作原理,源碼版助于了解內部詳情,讓我們一起學習吧研究基于...
摘要:寫文章不容易,點個贊唄兄弟專注源碼分享,文章分為白話版和源碼版,白話版助于理解工作原理,源碼版助于了解內部詳情,讓我們一起學習吧研究基于版本如果你覺得排版難看,請點擊下面鏈接或者拉到下面關注公眾號也可以吧原理源碼版之綁定組件自定義事件組件 寫文章不容易,點個贊唄兄弟專注 Vue 源碼分享,文章分為白話版和 源碼版,白話版助于理解工作原理,源碼版助于了解內部詳情,讓我們一起學習吧研究基于...
摘要:寫文章不容易,點個贊唄兄弟專注源碼分享,文章分為白話版和源碼版,白話版助于理解工作原理,源碼版助于了解內部詳情,讓我們一起學習吧研究基于版本如果你覺得排版難看,請點擊下面鏈接或者拉到下面關注公眾號也可以吧原理源碼版之綁定標簽事件這里的綁定 寫文章不容易,點個贊唄兄弟專注 Vue 源碼分享,文章分為白話版和 源碼版,白話版助于理解工作原理,源碼版助于了解內部詳情,讓我們一起學習吧研究基于...
摘要:表示虛擬節點,為什么叫虛擬節點呢,因為不是真的節點。因為是對象,不管還是瀏覽器,都可以統一操作,從而獲得了服務端渲染原生渲染手寫渲染函數等能力減少操作。 寫文章不容易,點個贊唄兄弟專注 Vue 源碼分享,文章分為白話版和 源碼版,白話版助于理解工作原理,源碼版助于了解內部詳情,讓我們一起學習吧研究基于 Vue版本 【2.5.17】 如果你覺得排版難看,請點擊 下面鏈接 或者 拉到 下...
閱讀 3704·2021-11-12 10:36
閱讀 3842·2021-09-22 15:48
閱讀 3551·2019-08-30 15:54
閱讀 2606·2019-08-29 16:44
閱讀 2374·2019-08-29 16:08
閱讀 2420·2019-08-29 16:06
閱讀 1294·2019-08-29 15:21
閱讀 3179·2019-08-29 12:39