日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁技術文章
文章詳情頁

vue 虛擬DOM快速入門

瀏覽:40日期:2022-09-30 15:41:37
虛擬 DOM什么是虛擬 dom

dom 是文檔對象模型,以節點樹的形式來表現文檔。

虛擬 dom 不是真正意義上的 dom。而是一個 javascript 對象。

正常的 dom 節點在 html 中是這樣表示:

<div class=’testId’> <p>你好</p> <p>歡迎光臨</p></div>

而在虛擬 dom 中大概是這樣:

{ tag: ’div’, attributes:{class: [’testId’] }, children:[// p 元素// p 元素 ]}

我們可以將虛擬 dom 拆分成兩部分進行理解:虛擬 + dom。

虛擬: 表示虛擬 dom 不是真正意義上的 dom,而是一個 javascript 對象; dom: 表示虛擬 dom 能以類似節點樹的形式表示文檔。 虛擬 dom 的作用

現在主流的框架都是聲明式操作 dom 的框架。我們只需要描述狀態與 dom 之間的映射關系即可,狀態到視圖(真實的 dom)的轉換,框架會幫我們做。

最粗暴的做法是將狀態渲染成視圖,每次更新狀態,都重新更新整個視圖。

這種做法的性能可想而知。比較好的想法是:狀態改變,只更新與狀態相關的 dom 節點。虛擬 dom 只是實現這個想法的其中一種方法而已。

具體做法:

狀態 -> 真實 dom(最初) 狀態 -> 虛擬 dom -> 真實 dom(使用虛擬 dom)

狀態改變,重新生成一份虛擬 dom,將上一份和這一份虛擬 dom 進行對比,找出需要更新的部分,更新真實 dom。

vue 中的虛擬 dom

真實的 dom 是由 節點(Node)組成,虛擬 dom 則是由虛擬節點(vNode)組成。

虛擬 dom 在 vue 中主要做兩件事:

提供與真實節點(Node)對應的虛擬節點(vNode) 將新的虛擬節點與舊的虛擬節點進行對比,找出需要差異,然后更新視圖

“虛擬 DOM”是我們對由 Vue 組件樹建立起來的整個 VNode 樹的稱呼 —— vue 官網

vNode什么是 vNode

上文提到,vNode(虛擬節點)對應的是真實節點(Node)。

vNode 可以理解成節點描述對象。描述了如何創建真實的 dom 節點。

vue.js 中有一個 vNode 類。可以使用它創建不同類型的 vNode 實例,不同類型的 vNode 對應著不同類型的 dom 元素。代碼如下:

export default class VNode { constructor ( tag?: string, data?: VNodeData, children?: ?Array<VNode>, text?: string, elm?: Node, context?: Component, componentOptions?: VNodeComponentOptions, asyncFactory?: Function ) { this.tag = tag this.data = data this.children = children this.text = text this.elm = elm this.ns = undefined this.context = context this.fnContext = undefined this.fnOptions = undefined this.fnScopeId = undefined this.key = data && data.key this.componentOptions = componentOptions this.componentInstance = undefined this.parent = undefined this.raw = false this.isStatic = false this.isRootInsert = true this.isComment = false this.isCloned = false this.isOnce = false this.asyncFactory = asyncFactory this.asyncMeta = undefined this.isAsyncPlaceholder = false } get child (): Component | void { return this.componentInstance }}

從代碼不難看出 vNode 類創建的實例,本質上就是一個普通的 javascript 對象。

vNode 的類型

前面我們已經介紹通過 vNode 類可以創建不同類型的 vNode。而不同類型的 vNode 是由有效屬性區分。例如 isComment = true 表示注釋節點;isCloned = true 表示克隆節點等等。

vNode 類型有:注釋節點、文本節點、克隆節點、元素節點、組件節點。

以下是注釋節點、文本節點和克隆節點的代碼:

/*注釋節點有效屬性:{isComment: true, text: ’注釋節點’}*/export const createEmptyVNode = (text: string = ’’) => { const node = new VNode() node.text = text // 注釋 node.isComment = true return node}/*文本節點有效屬性:{text: ’文本節點’}*/export function createTextVNode (val: string | number) { return new VNode(undefined, undefined, undefined, String(val))}// optimized shallow clone// used for static nodes and slot nodes because they may be reused across// 用于靜態節點和插槽節點// multiple renders, cloning them avoids errors when DOM manipulations rely// on their elm reference.// 克隆節點export function cloneVNode (vnode: VNode): VNode { const cloned = new VNode( vnode.tag, vnode.data, // #7975 // clone children array to avoid mutating original in case of cloning // a child. vnode.children && vnode.children.slice(), vnode.text, vnode.elm, vnode.context, vnode.componentOptions, vnode.asyncFactory ) cloned.ns = vnode.ns cloned.isStatic = vnode.isStatic cloned.key = vnode.key cloned.isComment = vnode.isComment cloned.fnContext = vnode.fnContext cloned.fnOptions = vnode.fnOptions cloned.fnScopeId = vnode.fnScopeId cloned.asyncMeta = vnode.asyncMeta // 標記是克隆節點 cloned.isCloned = true return cloned}

克隆節點其實就是將現有節點的所有屬性賦值到新節點中,最后用 cloned.isCloned = true 標記自身是克隆節點。

元素節點通常有以下 4 個屬性:

tag:節點名稱。例如 div、p data:節點上的數據。例如 class、style children:子節點 context:在組件內呈現

組件節點與元素節點類似,包含兩個獨有的屬性:

componentOptions:組件節點的選項參數,例如propsData、listeners、children、tag componentInstance:組件的實例 patch

前面已經介紹了虛擬 dom 在 vue 中做的第一件事:提供與真實節點(Node)對應的虛擬節點(vNode);接下來介紹第二件事:將新的虛擬節點與舊的虛擬節點進行對比,找出需要差異,然后更新視圖。

第二件事在 vue 中的實現叫做 patch,即打補丁、修補的意思。通過對比新舊 vNode,找出差異,然后在現有 dom 的基礎上進行修補,從而實現視圖更新。

對比 vNode 找差異是手段,更新視圖才是目的。

而更新視圖無非就是新增節點、刪除節點和更新節點。接下來我們逐一分析什么時候新增節點、在哪里新增;什么時候刪除節點,刪除哪個;什么時候更新節點,更新哪個;

注:當 vNode 與 oldVNode 不相同的時候,以 vNode 為準。

新增節點

一種情況是:vNode 存在而 oldVNode 不存在時,需要新增節點。最典型的是初次渲染,因為 odlVNode 是不存在的。

另一種情況是 vNode 與 oldVNode 完全不是同一個節點。這時就需要使用 vNode 生成真實的 dom 節點并插入到 oldVNode 指向的真實 dom 節點旁邊。oldVNode 則是一個被廢棄的節點。例如下面這種情況:

<div> <p v-if='type === ’A’'> 我是節點A </p> <span v-else-if='type === ’B’'> 我是與A完全不同的節點B </span></div>

當 type 由 A 變為 B,節點就會從 p 變成 span,由于 vNode 與 oldVNode 完全不是同一個節點,所以需要新增節點。

刪除節點

當節點只在 oldVNode 中存在時,直接將其刪除即可。

更新節點

前面介紹了新增節點和刪除節點的場景,發現它們有一個共同點:vNode 與 oldVNode 完全不相同。

但更常見的場景是 vNode 與 oldVNode 是同一個節點。然后我們需要對它們(vNode 與 oldVNode)進行一個更細致的對比,再對 oldVNode 對應的真實節點進行更新。

對于文本節點,邏輯自然簡單。首先對比新舊 vNode,發現是同一個節點,然后將 oldVNode 對應的 dom 節點的文本改成 vNode 中的文本即可。但對于復雜的 vNode,比如界面中的一顆樹組件,這個過程就會變得復雜。

新增節點 - 源碼分析

思考一下:前面說到 vNode 的類型有:注釋節點、文本節點、克隆節點、元素節點、組件節點。請問這幾種類型都會被創建并插入到 dom 中嗎?

答:只有注釋節點、文本節點、元素節點。因為 html 只認識這幾種。

由于只有上面三種節點類型,根據類型做響應的創建,然后插入對應的位置即可。

以元素節點為例,如果 vNode 有 tag 屬性,則說明是元素節點。則調用 createElement 方法創建對應的節點,接下來就通過 appendChild 方法插入到指定父節點中。如果父元素已經在視圖中,那么把元素插入到它下面將會自動渲染出來;如果 vNode 的 isComment 屬性是 true,則表示注釋節點;都不是則是文本節點;

通常元素里面會有子節點,所以這里涉及一個遞歸的過程,也就是將 vNode 中的 children 依次遍歷,創建節點,然后插入到父節點(父節點也就是剛剛創建出的 dom 節點)中,一層一層的遞歸進行。

請看源碼:

// 創建元素function createElm ( vnode, insertedVnodeQueue, parentElm, refElm, nested, ownerArray, index) { if (isDef(vnode.elm) && isDef(ownerArray)) { // This vnode was used in a previous render! // now it’s used as a new node, overwriting its elm would cause // potential patch errors down the road when it’s used as an insertion // reference node. Instead, we clone the node on-demand before creating // associated DOM element for it. vnode = ownerArray[index] = cloneVNode(vnode); } vnode.isRootInsert = !nested; // for transition enter check if (createComponent(vnode, insertedVnodeQueue, parentElm, refElm)) { return } var data = vnode.data; var children = vnode.children; var tag = vnode.tag; // 有 tag 屬性,表示是元素節點 if (isDef(tag)) { vnode.elm = vnode.ns ? nodeOps.createElementNS(vnode.ns, tag) // 創建元素。nodeOps 涉及到跨平臺 : nodeOps.createElement(tag, vnode); setScope(vnode); /* istanbul ignore if */ { // 遞歸創建子節點,并將子節點插入到父節點上 createChildren(vnode, children, insertedVnodeQueue); if (isDef(data)) {invokeCreateHooks(vnode, insertedVnodeQueue); } // 將 vnode 對應的元素插入到父元素中 insert(parentElm, vnode.elm, refElm); } // isComment 屬性表示注釋節點 } else if (isTrue(vnode.isComment)) { vnode.elm = nodeOps.createComment(vnode.text); // 插入父節點 insert(parentElm, vnode.elm, refElm); // 否則就是子節點 } else { vnode.elm = nodeOps.createTextNode(vnode.text); // 插入父節點 insert(parentElm, vnode.elm, refElm); }}// 遞歸創建子節點,并將子節點插入到父節點上。vnode 表示父節點function createChildren (vnode, children, insertedVnodeQueue) { if (Array.isArray(children)) { if (process.env.NODE_ENV !== ’production’) { checkDuplicateKeys(children); } // 依次創建子節點,并將子節點插入到父節點中 for (var i = 0; i < children.length; ++i) { createElm(children[i], insertedVnodeQueue, vnode.elm, null, true, children, i); } } else if (isPrimitive(vnode.text)) { nodeOps.appendChild(vnode.elm, nodeOps.createTextNode(String(vnode.text))); }}刪除節點 - 源碼分析

刪除節點非常簡單。直接看源碼:

// 刪除一組指定節點function removeVnodes (parentElm, vnodes, startIdx, endIdx) { for (; startIdx <= endIdx; ++startIdx) { var ch = vnodes[startIdx]; if (isDef(ch)) { if (isDef(ch.tag)) {removeAndInvokeRemoveHook(ch);invokeDestroyHook(ch); } else { // Text node// 刪除個節點removeNode(ch.elm); } } }}// 刪除單個節點function removeNode (el) { var parent = nodeOps.parentNode(el); // element may have already been removed due to v-html / v-text if (isDef(parent)) { // nodeOps里封裝了跨平臺的方法 nodeOps.removeChild(parent, el); }}

以上就是vue 虛擬DOM快速入門的詳細內容,更多關于vue 虛擬DOM的資料請關注好吧啦網其它相關文章!

標簽: Vue
相關文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
欧美中文高清| 久草精品视频| а√在线中文在线新版| 美腿丝袜亚洲三区| 国产精品久久亚洲不卡| 国产日韩欧美中文在线| 欧美性www| 国产精品videossex| 亚洲网址在线观看| 亚洲午夜免费| 日韩av一区二| 国产视频一区二| 久久99免费视频| 福利视频一区| 91精品精品| 亚洲综合不卡| 日日夜夜免费精品视频| 国产欧美久久一区二区三区| 久久99久久人婷婷精品综合| 国产一区三区在线播放| 五月天av在线| 亚洲国产成人精品女人| 久久xxxx精品视频| 免费日韩精品中文字幕视频在线| 日本大胆欧美人术艺术动态| 在线观看亚洲精品福利片| 亚洲毛片一区| 国产精品蜜月aⅴ在线| 久久精品国产一区二区| 亚洲黄色网址| 国产高清一区| 日本免费一区二区视频| 久久精品国产网站| 色婷婷久久久| 亚洲视频电影在线| 国产欧美二区| 色综合www| 免费成人在线视频观看| 日本不卡高清| 91欧美日韩| 久久福利一区| 久久不见久久见免费视频7 | 91成人精品在线| 国产成人精品免费视| 亚洲二区视频| 青青青国产精品| 蜜桃精品在线| 亚洲制服欧美另类| 岛国精品一区| 免费在线观看视频一区| 久久不见久久见中文字幕免费 | 午夜久久av | 97欧美在线视频| 久久福利精品| 国产不卡一区| 蜜桃久久精品一区二区| 精品视频一二| 蜜臀a∨国产成人精品| 国产一区精品福利| 影音国产精品| 国产一区二区三区四区| 99成人在线| 福利一区和二区| 在线看片日韩| 久久精品影视| 国产精成人品2018| 五月婷婷六月综合| 麻豆一区在线| 午夜久久av| 久久精品主播| 国产精品1luya在线播放| aⅴ色国产欧美| av中文字幕在线观看第一页 | 黄色精品视频| 日本不卡视频在线观看| 久久精品亚洲人成影院| 国产精品第一| 亚洲美女久久| 久久国产精品成人免费观看的软件| 久久精品xxxxx| 性一交一乱一区二区洋洋av| 国产aⅴ精品一区二区四区| 亚州国产精品| 红桃视频国产精品| 国产一区福利| 国产日韩一区二区三区在线播放 | 国产一区欧美| 精品伊人久久| 久久激情五月婷婷| 亚洲资源网站| 好看不卡的中文字幕| 欧美gv在线| 精品久久一区| 欧美日韩亚洲一区三区| 国产一区白浆| 婷婷综合社区| 久久精品123| 色婷婷色综合| 欧美国产另类| 国产精品免费不| 亚洲精品伦理| 蜜臀精品一区二区三区在线观看| 亚洲精品97| 91精品婷婷色在线观看| 成人一区而且| 久久精品三级| 国产精品免费精品自在线观看| 日韩欧美激情电影| 亚洲ww精品| 亚洲精品伊人| 美国三级日本三级久久99| 红桃视频国产一区| 国产字幕视频一区二区| 丝袜诱惑一区二区| 中文字幕人成乱码在线观看| 欧美国产极品| 美女毛片一区二区三区四区最新中文字幕亚洲 | 午夜日韩在线| 婷婷亚洲五月| 黄色在线一区| 一区福利视频| 午夜在线一区| 香蕉久久国产| 亚洲在线国产日韩欧美| 欧美不卡视频| 不卡在线一区| 亚洲一区二区三区高清不卡| 在线视频日韩| 一区二区三区四区日韩| 在线观看一区| 日韩欧美中文字幕电影| 亚洲精品福利| 国产午夜一区| 老色鬼精品视频在线观看播放| 国产精品欧美在线观看| 国产精品啊v在线| 国产成人a视频高清在线观看| 日韩av有码| 久久五月天小说| 欧美中文字幕| 亚洲综合色婷婷在线观看| 日韩精品一区二区三区中文在线| 欧美日韩18| 久久精品网址| 日韩精品免费一区二区三区| 午夜国产欧美理论在线播放| 视频一区欧美日韩| 日韩视频1区| 美女国产精品久久久| 鲁鲁在线中文| www在线观看黄色| 国产精品www.| 在线亚洲人成| 视频精品一区| 欧美一区二区三区高清视频| 午夜av一区| 中文字幕人成乱码在线观看| 91精品国产自产观看在线| 免费黄色成人| 成人在线网站| 另类小说一区二区三区| 亚洲伊人精品酒店| 婷婷综合激情| 欧美国产美女| 国产欧美日韩一级| 欧美高清不卡| 999视频精品| 99视频精品全部免费在线视频| 婷婷国产精品| 久久精品电影| 国产精品xxx在线观看| 亚洲天堂av资源在线观看| 欧美一区=区三区| 国产模特精品视频久久久久| 国产免费av一区二区三区| 精品国产aⅴ| 在线亚洲成人| 国产精品啊啊啊| re久久精品视频| 日韩av黄色在线| 天堂а√在线最新版中文在线| 丝袜国产日韩另类美女| 国产精品一区二区精品视频观看 | 蜜桃传媒麻豆第一区在线观看| 免费看久久久| 久久亚洲精品伦理| 国产在线视频欧美一区| 老牛影视一区二区三区| 成人污污视频| 日韩高清中文字幕一区| 日韩精品一区二区三区免费观看| 天堂av一区| 日韩精品久久久久久久电影99爱| 日韩精品五月天| 欧美日韩在线播放视频| 国产欧美高清| 免费成人性网站| 伊人久久在线| 日本视频一区二区| 好吊日精品视频|