日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

c++ gdb 绑定源码_【Vue原理】VNode 源码版

發布時間:2023/11/27 生活经验 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 c++ gdb 绑定源码_【Vue原理】VNode 源码版 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

↑點擊上方?“神仙朱”?一起研究Vue源碼吧

專注?Vue?源碼分享,文章分為白話版和?源碼版,白話版助于理解工作原理,源碼版助于了解內部詳情,讓我們一起學習吧

研究基于 Vue版本【2.5.17】

五一就這么過了,哎,大家快點進入工作狀態哈哈

今天就來探索?VNode?的源碼,VNode?是?Vue2?渲染機制中很重要的一部分,是深入Vue?必須了解的部分

我們以4個問題來開始我們的探索

1、vnode 是什么及其作用

2、vnode 什么時候生成

3、vnode 怎么生成

4、vnode 存放什么信息

5、vnode 存放在哪里

文章很長,看之前值做好準備

VNode是什么及作用

首先,第一個問題已經很爛了,網上有很多相關的內容,為了內容的完整性,所以也放上來哈哈。

VNode?表示?虛擬節點 Virtual DOM,為什么叫虛擬節點呢,因為不是真的?DOM?節點。

他只是用 javascript?對象來描述真實?DOM,這么描述,把DOM標簽,屬性,內容都變成?對象的屬性

就像用?JavaScript?對象描述一個人一樣

{sex:'男', name:'神仙朱', salary:5000,children:null}

過程就是,把你的?template?模板?描述成?VNode,然后一系列操作之后通過?VNode?形成真實DOM進行掛載

是什么?

JavaScript?對象

什么用?

1兼容性強,不受執行環境的影響。VNode?因為是?JS?對象,不管?Node?還是?瀏覽器,都可以統一操作, 從而獲得了服務端渲染、原生渲染、手寫渲染函數等能力

2減少操作?DOM。任何頁面的變化,都只使用 VNode?進行操作對比,只需要在最后一步掛載更新DOM,不需要頻繁操作DOM,從而提高頁面性能

VNode怎么生成

在?Vue?源碼中,vnode?是通過一個構造函數生成的,構造函數看起來挺簡單的

本來以為很多內容,帶著沉重的心情去探索,然后看到之后就放松了下來,看了一會,心情再次沉重了起來

其中涉及的內容還是挺多的....不然哪里來開篇的那么多問題

行了,看下?VNode?的構造函數

function VNode(
? ?tag, data, children,
? ?text, elm, context, ? ?componentOptions) { ? ?????this.tag = tag; // 標簽名 ? ?this.data = data; ? ?????this.children = children; // 子元素 ? ?this.text = text; // 文本內容 ? ?this.elm = elm; // Dom 節點 ? ?this.context = context; ? ?????this.componentOptions = componentOptions; ? ?????this.componentInstance = undefined; ? ?????this.parent = undefined; ? ?????this.isStatic = false; // 是否靜態節點 ? ?this.isComment = false; // 是否是注釋節點 ? ?this.isCloned = false; // 是否克隆節點};

看完上面,先不要糾結都是什么東西,先來走一遍

比如我們使用?vnode?去描述這樣一個template

<div class="parent" style="height:0" href="2222"> ? ?111111div>

使用?VNode?構造函數就可以生成下面的?VNode

{ ? ?

????tag: 'div', ? ?

????data: { ? ? ? ?

????????attrs:{href:"2222"}

? ? ? ?staticClass: "parent", ? ? ? ?

????????staticStyle: { ? ? ? ? ? ?

????????????height: "0"

? ? ? ?}

? ?}, ? ?

????children: [{ ? ? ? ?

????????tag: undefined, ? ? ? ?

????????text: "111111"

? ?}]
}

這個?JS?對象,就已經囊括了整個模板的所有信息,完全可以根據這個對象來構造真實DOM了

至于其中都是什么意思,請看下個問題

VNode存放什么信息

新建一個?vnode?的時候,包含了非常多的屬性,每個屬性都是節點的描述的一部分

我們只撿一些屬性來探索一下,了解主體即可

1普通屬性

1data

1、存儲節點的屬性,class,style?等

2、存儲綁定的事件

3、....其他

2elm

真實DOM?節點

生成VNode?的時候,并不存在真實?DOM

elm?會在需要創建DOM 時完成賦值,具體函數在?createElm?中

賦值語句就是一句(簡化了源碼)

3context

渲染這個模板的上下文對象

意思就是,template?里面的動態數據要從這個?context?中獲取,而 context?就是?Vue?實例

如果是頁面,那么context?就是本頁面的實例,如果是組件,context則是組件的實例

4?isStatic

是否是靜態節點

當一個節點被標記為靜態節點的時候,說明這個節點可以不用去更新它了,當數據變化的時候,可以忽略去比對他,以提高比對效率

2組件相關屬性

1parent

這個parent?表示是組件的外殼節點

額,什么是外殼節點,舉個栗子先吧

1、存在這樣一個組件?test

2、頁面中使用這個組件

誒,到這里就有意思了,組件其實應有兩種?VNode

頁面給

組件test?

解析成的?VNode

{

??? tag:"test",

??? children:undefined

}

組件內部生成的?VNode

{

??? tag:"?h2",

? ? children:[{

??? ???tag:undefined,

??? ???text:"我勒個去"

??? }]

}

這兩種VNode?名義上都是對的,都有理,誰是正牌不好說

最后尤大判定第一個?VNode?是?第二個?VNode?的爸爸,也就是外殼節點

外殼節點通常是?父組件和?子組件的?關聯,用于保存一些父組件傳給子組件的數據?等

2 componentInstance

這個顧名思義,就是組件生成的實例,保存在這里

上面?test?組件的外殼節點中的?componentInstance

3 componentOptions

這個就存儲一些?父子組件?PY?交易的證據

比如?props,事件,slot 什么的,打印看下

其中?children?保存的就是?slot,listeners?保存?事件,propsData?保存?props

VNode怎么生成

在初始化完選項,解析完模板之后,就需要掛載?DOM了。此時就需要生成?VNode,才能根據?VNode?生成?DOM?然后掛載

掛載?DOM?第一步,就是先執行渲染函數,得到整個模板的?VNode

比如有以下渲染函數,執行會返回?VNode,就是 _c?返回的VNode

function (){ 
? ?with(this){ ?
? ? ? ?return _c('div',{attrs:{"href":"xxxx"}},["1111"]).
? ?}
}

渲染函數會綁定上下文對象,加上?with?的作用,_c?其實就是?vm._c

現在就來看 vm._c?是什么東西

vm._c = function(a, b, c, d) { ? ?

????return createElement(vm, a, b, c, d, false);

};

function createElement(

????context, tag, data,

????children, normalizationType

) { ? ?

????var vnode; ? ?

????if (tag是正常html標簽) {

? ? ? ?vnode = new VNode(

????????????tag, data, children, undefined,

????????????undefined, context

????????);
? ?}
? ?else if (tag 是組件) {
? ? ? ?vnode = createComponent(

????????????Ctor, data, context,

????????????children, tag

????????);

? ?} ? ?

????return vnode

}

我們可以看到,正常標簽 和?組件會走不同流程

1正常標簽

比如有這樣一個正常標簽模板

解析成渲染函數如下

function (){ ? ?

????with(this){ ?

? ? ? ?return _c('div',{

????????????attrs:{"href":"xxxx"}},

????????????["1111"]

????????)

? ?}
}

看上面_c?源碼,可以知道經過 _c?把參數傳導,這樣去構建?VNode

new VNode(tag, data, children, undefined, undefined, context);
tag?'div'
data{attrs:{"href":"xxxx"}}
children?["1111"]
context?頁面實例

這樣就保存了?tag,data,children?和?context

2組件

比如頁面使用了test組件

解析成渲染函數如下

with(this){ ?
? ?return _c('div',[
? ? ? ?_c('test',
? ? ? ? ? ?{attrs:{"name":name}},
? ? ? ? ? ?["1111"]
? ? ? ?)
? ?],1)
}

看上面 _c?代碼知道 ,_c 會先調用?createComponent

createComponent(Ctor, data, context, children, tag);}
tag'test'
data{ attrs:{"name":name} }
children?["1111"]
context?頁面父實例(畢竟這是外殼節點,是在父實例中解析的)
Ctor組件的選項,然后變成組件的構造函數,這里可以先不管,后面會詳細講 Component?

createComponent 中也會調用?VNode?構造函數,生成VNode?并返回

function createComponent(

????Ctor, data, context,

????children, tag

) { ? ?

? ?// extractPropsFromVNodeData 作用是把傳入data的 attr 中屬于 props的篩選出來

? ?var propsData = extractPropsFromVNodeData(data, Ctor, tag); ? ?

????var vnode = new VNode(

? ? ? ?("vue-component-" + (Ctor.cid) + tag),
? ? ? ?data, undefined, undefined, undefined,

????????context, { ? ? ? ? ? ?

????????????Ctor: Ctor,

????????????// 父組件給子組件綁定的props
? ? ? ? ? ?propsData: propsData,

????????????// 父組件給子組件綁定的事件
? ? ? ? ? ?listeners: listeners,

? ? ? ? ? ?tag: tag, ? ? ? ? ? ?

????????????children: children

? ? ? ?}); ? ?

????return vnode

}

VNode存放在哪里

那么創建出來的?VNode?是否有被存起來,毫無疑問,肯定是要的啊

主要是三個位置存了?vnode,分別是

parent ,_vnode ,$vnode?

parent?上面已經說過,就先不提了,剩下兩個全部是掛在?Vue?實例一級屬性上的

打印一下組件的實例,可以很清楚看到這兩個屬性

下面來說說這兩個東西

1_vnode

_vnode?存放表示當前節點的?VNode

什么叫當前,也就是可以通過這個VNode?直接映射成?當前真實DOM

他的作用是什么呢?

用來比對更新,比如你的數據變化了,此時會生成一個新的?VNode,然后再拿到保存的_vnode 對比,就可以得到最小區域,從而只用更新這部分

所以, _vnode?存放的可以說是當前節點,也可以說是舊節點

另外,_vnode?中保存有一個?parent,這個parent?就是外殼節點,上面說?vnode?的時候已經說過了

在哪里賦值?

我們來完整地走一遍流程,涉及源碼很多,但是我已經非常精簡了,大概了解個流程

function Vue() {
? ?...初始化組件選項等
? ?mountComponent()

}

function mountComponent() {


? ?....解析模板,生成渲染函數
?
? ?// 用于生成VNode,生成DOM,掛載DOM
? ?updateComponent = function() {
? ? ? ?vm._update(vm._render());

? ?}; ? ?

? ?// 新建 watcher,保存updateComponent為更新函數,新建的時候會立即執行一遍
? ?new Watcher(vm, updateComponent)

}

function Watcher(vm, expOrFn) { ? ?

????this.getter = expOrFn ; ? ?

????this.getter()

}

// 執行前面解析得到的渲染函數,返回生成的 VNode

Vue.prototype._render = () {}

// 根據vnode,生成DOM 掛載

Vue.prototype._update = function(vnode) { ? ?

????var prevVnode = vm._vnode;

? ?vm._vnode = vnode; ? ?

????if (不存在舊節點) { ...使用vnode創建DOM并直接掛載 } ? ?

????else { ...存在舊節點,開始比對舊節點和新節點,然后創建DOM并掛載 }

}

2$vnode

$vnode?只有組件實例才有,因為 $vnode?存放的是外殼節點,頁面實例中是不存在 $vnode?的

本來也想走下流程的,無奈兜兜轉轉太多,涉及源碼更多

在哪里進行賦值?

我就放最后一步?updateChildComponent

updateChildComponent?會在上個 _vnode?提到的?vm._update?執行流程中調用

function updateChildComponent(
? ?vm,
parentVnode

) {

? ?vm.$options._parentVnode = parentVnode;
? ?
vm.$vnode = parentVnode;
? ?if (vm._vnode) {
? ? ? ?vm._vnode.parent = parentVnode;
? ?}
}

最后

鑒于本人能力有限,難免會有疏漏錯誤的地方,請大家多多包涵,如果有任何描述不當的地方,歡迎后臺聯系本人,領取紅包

長按關注>>>

盤它

總結

以上是生活随笔為你收集整理的c++ gdb 绑定源码_【Vue原理】VNode 源码版的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。