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

您的位置:首頁技術(shù)文章
文章詳情頁

vue頁面更新patch的實現(xiàn)示例

瀏覽:197日期:2023-01-30 08:38:24

patch的流程

組件頁面渲染時,將render返回的新vnode(新節(jié)點)和組件實例保存的vnode(舊節(jié)點)作為參數(shù),調(diào)用patch方法,更新DOM。

判斷兩個節(jié)點是否相同

處理過程中,需要判斷節(jié)點是否相同。相同節(jié)點需要滿足以下條件:

key相同 標(biāo)簽類型相同 注釋節(jié)點標(biāo)識相同,都是注釋節(jié)點,或者都不是注釋節(jié)點 data的值狀態(tài)相同,或者都有值,或者都沒值

function sameVnode (a, b) {// 判斷兩個VNode節(jié)點是否是同一個節(jié)點 return ( a.key === b.key && // key相同 ( a.tag === b.tag && // tag相同 a.isComment === b.isComment && // 注釋節(jié)點標(biāo)識相同 isDef(a.data) === isDef(b.data) && // data值狀態(tài)相同 sameInputType(a, b) // input的type相同 ) )}

patch方法

patch判斷流程如下:

a) 如果新節(jié)點為空,此時舊節(jié)點存在(組件銷毀時),調(diào)用舊節(jié)點destroy生命周期函數(shù)

b) 如果舊節(jié)點為空,根據(jù)新節(jié)點創(chuàng)建DOM

c) 其他(如果新舊節(jié)點都存在)

a) 舊節(jié)點不是DOM(組件節(jié)點),且新舊節(jié)點相同 執(zhí)行patchVnode b) 舊節(jié)點是DOM元素或者兩個節(jié)點不相同 創(chuàng)建新節(jié)點DOM,銷毀舊節(jié)點以及DOM。

function patch (oldVnode, vnode, hydrating, removeOnly) { if (isUndef(vnode)) { if (isDef(oldVnode)) { invokeDestroyHook(oldVnode); } return } ... if (isUndef(oldVnode)) { isInitialPatch = true;// 組件初始加載 createElm(vnode, insertedVnodeQueue); } else { var isRealElement = isDef(oldVnode.nodeType); if (!isRealElement && sameVnode(oldVnode, vnode)) { patchVnode(oldVnode, vnode, insertedVnodeQueue, null, null, removeOnly); } else { ... var oldElm = oldVnode.elm; var parentElm = nodeOps.parentNode(oldElm);// 獲取父元素 // create new node createElm( vnode, insertedVnodeQueue, oldElm._leaveCb ? null : parentElm, nodeOps.nextSibling(oldElm)// 獲取緊跟的弟弟元素 ); if (isDef(parentElm)) { removeVnodes(parentElm, [oldVnode], 0, 0);// 銷毀舊節(jié)點以及DOM元素 } else if (isDef(oldVnode.tag)) { invokeDestroyHook(oldVnode); } } } invokeInsertHook(vnode, insertedVnodeQueue, isInitialPatch); return vnode.elm }}

patchVnode方法

當(dāng)兩個節(jié)點相同時,執(zhí)行patchVnode方法。在處理各種情況之前,會將舊節(jié)點elm屬性值賦值給新節(jié)點的elm屬性,保持elm保持一致。

具體流程如下:

a)如果新舊節(jié)點完全相同(引用相同 oldVnode === vnode)

直接返回不處理

b) 如果新節(jié)點不是文本節(jié)點

a)都存在子節(jié)點,新舊節(jié)點的子節(jié)點數(shù)組引用不同(oldCh !== ch) updateChildren b)新節(jié)點有子節(jié)點,舊節(jié)點沒有 1)查重子節(jié)點(key) 2)如果舊節(jié)點是文本節(jié)點,先清空文本 3)創(chuàng)建子節(jié)點DOM元素 c)舊節(jié)點有子節(jié)點,新節(jié)點沒有 移除子節(jié)點以及DOM d)舊節(jié)點是文本節(jié)點 清除文本 c)如果新節(jié)點是文本節(jié)點,并且和舊節(jié)點文本不相同 則直接替換文本內(nèi)容。 d)其他(新節(jié)點是文本節(jié)點,并且和舊節(jié)點相同) 不處理

function patchVnode ( oldVnode, vnode, insertedVnodeQueue, ownerArray, index, removeOnly ) { if (oldVnode === vnode) { return } ... if (isUndef(vnode.text)) { if (isDef(oldCh) && isDef(ch)) { if (oldCh !== ch) { updateChildren(elm, oldCh, ch, insertedVnodeQueue, removeOnly); } } else if (isDef(ch)) { if (process.env.NODE_ENV !== ’production’) { checkDuplicateKeys(ch); } if (isDef(oldVnode.text)) { nodeOps.setTextContent(elm, ’’); } addVnodes(elm, null, ch, 0, ch.length - 1, insertedVnodeQueue); } else if (isDef(oldCh)) { removeVnodes(elm, oldCh, 0, oldCh.length - 1); } else if (isDef(oldVnode.text)) { nodeOps.setTextContent(elm, ’’); } } else if (oldVnode.text !== vnode.text) { nodeOps.setTextContent(elm, vnode.text); } ... }

updateChildren方法

updateChildren方法處理相同新舊節(jié)點的子節(jié)點。方法定義了以下變量(updateChildren的節(jié)點都表示的是子節(jié)點):

var oldStartIdx = 0;// 表示當(dāng)前正在處理的舊起始節(jié)點序號 var newStartIdx = 0;// 表示當(dāng)前正在處理的新起始節(jié)點序號 var oldEndIdx = oldCh.length - 1;// 表示當(dāng)前正在處理的舊結(jié)尾節(jié)點序號 var oldStartVnode = oldCh[0];// 表示當(dāng)前正在處理的舊起始節(jié)點 var oldEndVnode = oldCh[oldEndIdx];// 表示當(dāng)前正在處理的舊結(jié)尾節(jié)點 var newEndIdx = newCh.length - 1;// 表示當(dāng)前正在處理的新結(jié)尾節(jié)點序號 var newStartVnode = newCh[0];// 表示當(dāng)前正在處理的新起始節(jié)點 var newEndVnode = newCh[newEndIdx];// 表示當(dāng)前正在處理的新結(jié)尾節(jié)點 var oldKeyToIdx, // 尚未處理的舊節(jié)點key值映射 idxInOld, // 與新節(jié)點key值相同的舊節(jié)點序號 vnodeToMove, // 與新節(jié)點key值相同的舊節(jié)點 refElm;// 指向當(dāng)前正在處理的新結(jié)尾節(jié)點的后一個節(jié)點(已處理)的DOM元素

根據(jù)新舊節(jié)點的對比結(jié)果,更新DOM元素,此過程并不改變新舊節(jié)點的排序。序號指向正在處理的節(jié)點,分別是新舊節(jié)點的起始和結(jié)尾節(jié)點。對比過程以新起始節(jié)點為主導(dǎo),對比方向是由兩側(cè)向中間。優(yōu)先比對新舊節(jié)點的起始節(jié)點和結(jié)尾節(jié)點,再查找與新起始節(jié)點相同的且未處理的舊節(jié)點。當(dāng)舊節(jié)點全部處理完(舊起始和結(jié)尾序號重疊),此時新節(jié)點可能未處理完,就添加新節(jié)點DOM元素。當(dāng)新節(jié)點全部處理完(新起始和結(jié)尾序號重疊),可能存在舊節(jié)點,就刪除舊節(jié)點DOM元素。

具體流程如下:

新舊子節(jié)點的起始序號不大于結(jié)尾序號時,執(zhí)行以下流程:

a)如果舊子節(jié)點兩側(cè)存在undefined節(jié)點

舊起始節(jié)點undefined,oldStartVnode = oldCh[++oldStartIdx] 舊結(jié)尾節(jié)點undefined,oldEndVnode = oldCh[--oldEndIdx]

b)新舊子節(jié)點的起始節(jié)點相同(前后比較)

patchVNode更新DOM內(nèi)容 oldStartVnode = oldCh[++oldStartIdx] newStartVnode = newCh[++newStartIdx]

c)新舊子節(jié)點的結(jié)尾節(jié)點相同(前后比較)

patchVNode更新DOM內(nèi)容 oldEndVnode = oldCh[--oldEndIdx] newEndVnode = newCh[--newEndIdx]

d)舊起始節(jié)點和新結(jié)尾節(jié)點相同(前后比較)

patchVNode更新DOM內(nèi)容 將舊起始節(jié)點DOM添加到舊結(jié)尾節(jié)點DOM前面 oldStartVnode = oldCh[++oldStartIdx] newEndVnode = newCh[--newEndIdx]

e)舊結(jié)尾節(jié)點和新起始節(jié)點相同(前后比較)

patchVNode更新DOM內(nèi)容 將舊結(jié)尾節(jié)點DOM添加到舊起始節(jié)點DOM前面 oldEndVnode = oldCh[--oldEndIdx] newStartVnode = newCh[++newStartIdx]

f)其他(緩存尚未處理的舊節(jié)點key值,依此判斷舊節(jié)點中是否存在和新起始節(jié)點相同的節(jié)點)

a)尚未處理的舊節(jié)點中不存在與新起始節(jié)點相同的節(jié)點 創(chuàng)建新節(jié)點DOM并添加到舊起始節(jié)點DOM的前面 newStartVnode = newCh[++newStartIdx] b)舊節(jié)點中存在與新起始節(jié)點key相同的節(jié)點 a)舊節(jié)點中存在與新起始節(jié)點相同的節(jié)點 patchVode 將相同的舊節(jié)點DOM添加到舊起始節(jié)點DOM前面 將相同的舊節(jié)點置為undefinedoldCh[idxInOld] = undefined newStartVnode = newCh[++newStartIdx] b)key相同,但標(biāo)簽類型不同的節(jié)點 創(chuàng)建新節(jié)點DOM并添加到舊起始節(jié)點DOM的前面 newStartVnode = newCh[++newStartIdx]

循環(huán)結(jié)束

a)如果舊節(jié)點遍歷完(oldStartIdx > oldEndIdx)

把剩余未處理新節(jié)點DOM添加到上一個新結(jié)尾節(jié)點DOM前面(從新起始節(jié)點到新結(jié)尾節(jié)點,都未處理過)

b)如果新節(jié)點遍歷完(newStartIdx > newEndIdx)

移除舊起始和結(jié)尾節(jié)點以及他們之間的節(jié)點的DOM(從舊起始節(jié)點到舊結(jié)尾節(jié)點,可能存在處理過的節(jié)點,但處理過已被置為undefined)

function updateChildren (parentElm, oldCh, newCh, insertedVnodeQueue, removeOnly) { var oldStartIdx = 0;// 表示當(dāng)前正在處理的舊起始節(jié)點序號 var newStartIdx = 0;// 表示當(dāng)前正在處理的新起始節(jié)點序號 var oldEndIdx = oldCh.length - 1;// 表示當(dāng)前正在處理的舊結(jié)尾節(jié)點序號 var oldStartVnode = oldCh[0];// 表示當(dāng)前正在處理的舊起始節(jié)點 var oldEndVnode = oldCh[oldEndIdx];// 表示當(dāng)前正在處理的舊結(jié)尾節(jié)點 var newEndIdx = newCh.length - 1;// 表示當(dāng)前正在處理的新結(jié)尾節(jié)點序號 var newStartVnode = newCh[0];// 表示當(dāng)前正在處理的新起始節(jié)點 var newEndVnode = newCh[newEndIdx];// 表示當(dāng)前正在處理的新結(jié)尾節(jié)點 var oldKeyToIdx, idxInOld, vnodeToMove, refElm; ... while (oldStartIdx <= oldEndIdx && newStartIdx <= newEndIdx) { if (isUndef(oldStartVnode)) { oldStartVnode = oldCh[++oldStartIdx]; // Vnode has been moved left } else if (isUndef(oldEndVnode)) { oldEndVnode = oldCh[--oldEndIdx]; } else if (sameVnode(oldStartVnode, newStartVnode)) { patchVnode(oldStartVnode, newStartVnode, insertedVnodeQueue, newCh, newStartIdx); oldStartVnode = oldCh[++oldStartIdx]; newStartVnode = newCh[++newStartIdx]; } else if (sameVnode(oldEndVnode, newEndVnode)) { patchVnode(oldEndVnode, newEndVnode, insertedVnodeQueue, newCh, newEndIdx); oldEndVnode = oldCh[--oldEndIdx]; newEndVnode = newCh[--newEndIdx]; } else if (sameVnode(oldStartVnode, newEndVnode)) { // Vnode moved right patchVnode(oldStartVnode, newEndVnode, insertedVnodeQueue, newCh, newEndIdx); canMove && nodeOps.insertBefore(parentElm, oldStartVnode.elm, nodeOps.nextSibling(oldEndVnode.elm)); oldStartVnode = oldCh[++oldStartIdx]; newEndVnode = newCh[--newEndIdx]; } else if (sameVnode(oldEndVnode, newStartVnode)) { // Vnode moved left patchVnode(oldEndVnode, newStartVnode, insertedVnodeQueue, newCh, newStartIdx); canMove && nodeOps.insertBefore(parentElm, oldEndVnode.elm, oldStartVnode.elm); oldEndVnode = oldCh[--oldEndIdx]; newStartVnode = newCh[++newStartIdx]; } else { if (isUndef(oldKeyToIdx)) { oldKeyToIdx = createKeyToOldIdx(oldCh, oldStartIdx, oldEndIdx); }// 緩存尚未處理的舊節(jié)點key值 idxInOld = isDef(newStartVnode.key) ? oldKeyToIdx[newStartVnode.key] : findIdxInOld(newStartVnode, oldCh, oldStartIdx, oldEndIdx); if (isUndef(idxInOld)) { // New element createElm(newStartVnode, insertedVnodeQueue, parentElm, oldStartVnode.elm, false, newCh, newStartIdx); } else { vnodeToMove = oldCh[idxInOld]; if (sameVnode(vnodeToMove, newStartVnode)) { patchVnode(vnodeToMove, newStartVnode, insertedVnodeQueue, newCh, newStartIdx); oldCh[idxInOld] = undefined; canMove && nodeOps.insertBefore(parentElm, vnodeToMove.elm, oldStartVnode.elm); } else { // same key but different element. treat as new element createElm(newStartVnode, insertedVnodeQueue, parentElm, oldStartVnode.elm, false, newCh, newStartIdx); } } newStartVnode = newCh[++newStartIdx]; } } if (oldStartIdx > oldEndIdx) { refElm = isUndef(newCh[newEndIdx + 1]) ? null : newCh[newEndIdx + 1].elm; addVnodes(parentElm, refElm, newCh, newStartIdx, newEndIdx, insertedVnodeQueue); } else if (newStartIdx > newEndIdx) { removeVnodes(parentElm, oldCh, oldStartIdx, oldEndIdx); } }

updateChildren的示例:

1.左邊表示新舊節(jié)點,節(jié)點下面標(biāo)識起始和結(jié)尾節(jié)點(即正在處理的節(jié)點)。右邊表示當(dāng)前的DOM。

vue頁面更新patch的實現(xiàn)示例

2.新節(jié)點的起始和結(jié)尾節(jié)點與舊節(jié)點的起始和結(jié)尾節(jié)點互不相同,并且在舊節(jié)點中未找到與新起始節(jié)點(新節(jié)點f)相同的節(jié)點。所以創(chuàng)建節(jié)點f的DOM并添加到舊起始節(jié)點(舊節(jié)點a)DOM的前面,然后新起始節(jié)點序號加1,表示新節(jié)點f已處理,當(dāng)前正在處理新起始節(jié)點c。

vue頁面更新patch的實現(xiàn)示例

3.新節(jié)點的起始和結(jié)尾節(jié)點與舊節(jié)點的起始和結(jié)尾節(jié)點互不相同,但在舊節(jié)點中找到與新起始節(jié)點(節(jié)點c)相同的節(jié)點。所以將舊節(jié)點c的DOM添加到舊起始節(jié)點(舊節(jié)點a)DOM的前面,舊節(jié)點c置空,然后新起始節(jié)點序號加1,表示新節(jié)點c已處理,當(dāng)前正在處理新起始節(jié)點e。

vue頁面更新patch的實現(xiàn)示例

4.新起始節(jié)點(新節(jié)點e)和舊結(jié)尾節(jié)點(舊節(jié)點e)相同。更新舊節(jié)點e的DOM內(nèi)容,并將舊節(jié)點e的DOM移動到舊起始節(jié)點(舊節(jié)點a)DOM的前面,舊結(jié)尾節(jié)點序號減1,新起始節(jié)點加1,表示新舊節(jié)點e已處理,當(dāng)前正在處理的是新起始節(jié)點g和舊結(jié)尾節(jié)點d。

vue頁面更新patch的實現(xiàn)示例

5.新結(jié)尾節(jié)點(新節(jié)點d)和舊結(jié)尾節(jié)點(舊節(jié)點d)相同。僅更新舊節(jié)點d的DOM內(nèi)容。新結(jié)尾節(jié)點序號減1,舊結(jié)尾節(jié)點序號減1,表示新舊節(jié)點d已處理,當(dāng)前正在處理的是新結(jié)尾節(jié)點g和舊結(jié)尾節(jié)點c。由于舊節(jié)點c為空,則舊結(jié)尾節(jié)點為b。

vue頁面更新patch的實現(xiàn)示例

6.新節(jié)點的起始和結(jié)尾節(jié)點與舊節(jié)點的起始和結(jié)尾節(jié)點互不相同,并且在舊節(jié)點中未找到與新起始節(jié)點(新節(jié)點g)相同的節(jié)點。所以創(chuàng)建節(jié)點g的DOM并添加到舊起始節(jié)點(舊節(jié)點a)DOM的前面,然后新起始節(jié)點序號加1,表示新節(jié)點g已處理,當(dāng)前正在處理新起始節(jié)點d。

vue頁面更新patch的實現(xiàn)示例

7.由于新起始和結(jié)尾節(jié)點序號重疊,新節(jié)點已經(jīng)處理完畢,存在尚未處理的舊節(jié)點,則移除未處理的舊節(jié)點DOM。

vue頁面更新patch的實現(xiàn)示例

8.結(jié)束,最終的DOM。

vue頁面更新patch的實現(xiàn)示例

到此這篇關(guān)于vue頁面更新patch的實現(xiàn)示例的文章就介紹到這了,更多相關(guān)vue 更新patch內(nèi)容請搜索好吧啦網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持好吧啦網(wǎng)!

標(biāo)簽: Vue
相關(guān)文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
999久久久91| 韩日一区二区| 亚洲成人精选| 99视频精品视频高清免费| 欧美亚洲国产激情| 午夜在线视频一区二区区别| 视频一区二区中文字幕| 亚洲精品少妇| 国产精品麻豆成人av电影艾秋 | 亚洲精品在线二区| 性欧美长视频| 日韩高清欧美激情| 欧美xxxx性| 999久久久91| 爽爽淫人综合网网站| 日韩精品一区二区三区中文在线 | 久久99伊人| 久久成人一区| 国产欧美日韩免费观看| 国内不卡的一区二区三区中文字幕| 欧美国产91| 国产午夜精品一区二区三区欧美| 国产精品片aa在线观看| 国产拍在线视频| 国产亚洲精品v| 国产精品久久| 伊人久久大香线蕉av不卡| 国产精品普通话对白| 国产精品毛片视频| 欧美日韩国产探花| 欧美日韩一视频区二区| 韩国久久久久久| 爽爽淫人综合网网站| 久久精品女人| 国产一区白浆| 麻豆免费精品视频| 国产精品呻吟| 精品免费av一区二区三区| 午夜久久tv| 国产精品美女在线观看直播| 伊人成人网在线看| 久久97视频| 免费观看在线色综合| 精品国产18久久久久久二百| 噜噜噜躁狠狠躁狠狠精品视频 | 日本午夜大片a在线观看| 欧美日韩第一| 国产精品66| 另类国产ts人妖高潮视频| 捆绑调教美女网站视频一区| 国产日韩专区| 亚洲精品国产嫩草在线观看| 97久久中文字幕| 亚洲夜间福利| 精品视频高潮| 伊人久久亚洲| 一区二区三区四区在线看| 日韩激情av在线| 欧美午夜精品一区二区三区电影| 国产中文在线播放| 亚洲精品综合| 久久精品一区二区不卡| 国产欧美日韩视频在线 | 欧美精品福利| 黄色亚洲大片免费在线观看| 国产精品久久久久蜜臀 | 美腿丝袜亚洲三区| 午夜欧美视频| 久久青青视频| 国产伦精品一区二区三区千人斩 | 99在线精品免费视频九九视 | 免费观看久久av| 老司机免费视频一区二区三区| 国产一区2区在线观看| 中文字幕一区二区av| 好吊日精品视频| 色婷婷狠狠五月综合天色拍| 久久精品网址| 国产精品s色| 国产探花在线精品| 亚洲综合三区| 91久久视频| 一级欧洲+日本+国产| 日韩精品水蜜桃| 日韩中文影院| 青青久久av| 九九久久电影| 欧美精品自拍| 亚洲激情av| 国精品一区二区| 在线一区电影| 蘑菇福利视频一区播放| 免费人成网站在线观看欧美高清| 国产亚洲一区二区三区啪| 亚洲最大av| 午夜在线视频一区二区区别| 美女国产一区| 自拍自偷一区二区三区| 日韩一区二区三区在线看| av成人国产| 99国产精品| 亚洲一区二区三区久久久| 亚洲三级网址| 国产麻豆精品| 精品国产第一福利网站| 香蕉久久精品| 国产视频欧美| 一区二区日韩免费看| 啪啪亚洲精品| 免费一区二区三区在线视频| 国产精品久久国产愉拍| 国产一区二区精品久| 成人精品天堂一区二区三区| 午夜国产一区二区| 免费看欧美美女黄的网站| 日本99精品| 精品国产a一区二区三区v免费| 亚洲视频www| 日韩制服丝袜先锋影音| 97久久精品| 成人福利视频| 国产亚洲激情| 91九色综合| 在线人成日本视频| 一区二区自拍| 婷婷亚洲成人| 国产亚洲观看| 毛片在线网站| 亚洲三级精品| 久久精品国产网站| 五月天综合网站| 欧美日韩国产一区二区在线观看| 精品日韩毛片| 婷婷综合电影| 国产高清不卡| 亚洲一区导航| 国产成人精品一区二区三区视频| 日本亚洲视频| 麻豆国产精品一区二区三区| 久久美女精品| 亚洲精品影院在线观看| 精品国产黄a∨片高清在线| 尹人成人综合网| 88久久精品| 久久久蜜桃一区二区人| 日本麻豆一区二区三区视频| 精品免费av在线| 青青青国产精品| 日本精品影院| 国产精品欧美一区二区三区不卡| 亚洲精品免费观看| 久久亚洲道色| 六月天综合网| 91一区二区| 免费久久99精品国产自在现线| 狠狠操综合网| 国产精品中文| 伊人成人在线视频| 国产一区精品福利| 亚洲欧美专区| 青青青免费在线视频| 日韩午夜视频在线| 婷婷综合六月| 国产精品久久久久久妇女| 日韩午夜精品| 日韩精品不卡一区二区| 欧美日韩黄网站| 性色一区二区| 日韩精品水蜜桃| 欧美成a人片免费观看久久五月天| 国产精选久久| 日韩一级不卡| 日韩精品欧美激情一区二区| 国产精品视频3p| 亚洲精品综合| 国产精品免费看| 久久久久国产| 麻豆国产欧美日韩综合精品二区| 国产精品jk白丝蜜臀av小说| 在线亚洲欧美| 少妇精品导航| 国产一区二区三区久久| 奇米亚洲欧美| 综合一区av| 视频一区二区三区中文字幕| 久久精品国内一区二区三区水蜜桃| 久久香蕉国产| 欧美a级一区二区| 日韩av一区二区三区| 日本欧洲一区二区| 红桃视频国产精品| 日韩在线二区| 精品视频黄色| 精品一区二区男人吃奶| 国产伦理一区| 欧美亚洲自偷自偷| 日韩欧美三区| 日韩精品欧美大片| 日韩精品一区二区三区免费视频| 精品国产乱码久久久久久樱花|