中文字幕第五页-中文字幕第页-中文字幕韩国-中文字幕最新-国产尤物二区三区在线观看-国产尤物福利视频一区二区

vue頁面更新patch的

本文將為大家詳細介紹“vue頁面更新patch的”,內容步驟清晰詳細,細節處理妥當,而小編每天都會更新不同的知識點,希望這篇“vue頁面更新patch的”能夠給你意想不到的收獲,請大家跟著小編的思路慢慢深入,具體內容如下,一起去收獲新知識吧。

成都創新互聯主營冠縣網站建設的網絡公司,主營網站建設方案,app開發定制,冠縣h5微信小程序定制開發搭建,冠縣網站營銷推廣歡迎冠縣等地區企業咨詢

Vue的優點

Vue具體輕量級框架、簡單易學、雙向數據綁定、組件化、數據和結構的分離、虛擬DOM、運行速度快等優勢,Vue中頁面使用的是局部刷新,不用每次跳轉頁面都要請求所有數據和dom,可以大大提升訪問速度和用戶體驗。

patch的流程

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

判斷兩個節點是否相同

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

  • key相同

  • 標簽類型相同

  • 注釋節點標識相同,都是注釋節點,或者都不是注釋節點

  • data的值狀態相同,或者都有值,或者都沒值

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

patch方法

patch判斷流程如下:

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

b) 如果舊節點為空,根據新節點創建DOM

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

  • a) 舊節點不是DOM(組件節點),且新舊節點相同

    • 執行patchVnode

  • b) 舊節點是DOM元素或者兩個節點不相同

    • 創建新節點DOM,銷毀舊節點以及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);// 銷毀舊節點以及DOM元素
    } else if (isDef(oldVnode.tag)) {
     invokeDestroyHook(oldVnode);
    }
   }
  }
  invokeInsertHook(vnode, insertedVnodeQueue, isInitialPatch);
  return vnode.elm
 }
}

patchVnode方法

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

具體流程如下:

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

  • 直接返回不處理

b) 如果新節點不是文本節點

  • a)都存在子節點,新舊節點的子節點數組引用不同(oldCh !== ch)

    • updateChildren

  • b)新節點有子節點,舊節點沒有

    • 1)查重子節點(key)

    • 2)如果舊節點是文本節點,先清空文本

    • 3)創建子節點DOM元素

  • c)舊節點有子節點,新節點沒有

    • 移除子節點以及DOM

  • d)舊節點是文本節點

    • 清除文本

  • c)如果新節點是文本節點,并且和舊節點文本不相同

    • 則直接替換文本內容。

  • d)其他(新節點是文本節點,并且和舊節點相同)

    • 不處理

 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方法處理相同新舊節點的子節點。方法定義了以下變量(updateChildren的節點都表示的是子節點):

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

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

具體流程如下:

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

a)如果舊子節點兩側存在undefined節點

  • 舊起始節點undefined,oldStartVnode = oldCh[++oldStartIdx]

  • 舊結尾節點undefined,oldEndVnode = oldCh[--oldEndIdx]

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

  • patchVNode更新DOM內容

  • oldStartVnode = oldCh[++oldStartIdx]

  • newStartVnode = newCh[++newStartIdx]

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

  • patchVNode更新DOM內容

  • oldEndVnode = oldCh[--oldEndIdx]

  • newEndVnode = newCh[--newEndIdx]

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

  • patchVNode更新DOM內容

  • 將舊起始節點DOM添加到舊結尾節點DOM前面

  • oldStartVnode = oldCh[++oldStartIdx]

  • newEndVnode = newCh[--newEndIdx]

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

  • patchVNode更新DOM內容

  • 將舊結尾節點DOM添加到舊起始節點DOM前面

  • oldEndVnode = oldCh[--oldEndIdx]

  • newStartVnode = newCh[++newStartIdx]

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

  • a)尚未處理的舊節點中不存在與新起始節點相同的節點

    • 創建新節點DOM并添加到舊起始節點DOM的前面

    • newStartVnode = newCh[++newStartIdx]

  • b)舊節點中存在與新起始節點key相同的節點

    • 創建新節點DOM并添加到舊起始節點DOM的前面

    • newStartVnode = newCh[++newStartIdx]

    • patchVode

    • 將相同的舊節點DOM添加到舊起始節點DOM前面

    • 將相同的舊節點置為undefinedoldCh[idxInOld] = undefined

    • newStartVnode = newCh[++newStartIdx]

    • a)舊節點中存在與新起始節點相同的節點

    • b)key相同,但標簽類型不同的節點

循環結束

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

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

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

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

function updateChildren (parentElm, oldCh, newCh, insertedVnodeQueue, removeOnly) {
  var oldStartIdx = 0;// 表示當前正在處理的舊起始節點序號
  var newStartIdx = 0;// 表示當前正在處理的新起始節點序號
  var oldEndIdx = oldCh.length - 1;// 表示當前正在處理的舊結尾節點序號
  var oldStartVnode = oldCh[0];// 表示當前正在處理的舊起始節點
  var oldEndVnode = oldCh[oldEndIdx];// 表示當前正在處理的舊結尾節點
  var newEndIdx = newCh.length - 1;// 表示當前正在處理的新結尾節點序號
  var newStartVnode = newCh[0];// 表示當前正在處理的新起始節點
  var newEndVnode = newCh[newEndIdx];// 表示當前正在處理的新結尾節點
  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); }// 緩存尚未處理的舊節點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.左邊表示新舊節點,節點下面標識起始和結尾節點(即正在處理的節點)。右邊表示當前的DOM。

vue頁面更新patch的

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

vue頁面更新patch的

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

vue頁面更新patch的

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

vue頁面更新patch的

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

vue頁面更新patch的

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

vue頁面更新patch的

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

vue頁面更新patch的

8.結束,最終的DOM。

vue頁面更新patch的

如果你能讀到這里,小編希望你對“vue頁面更新patch的”這一關鍵問題有了從實踐層面最深刻的體會,具體使用情況還需要大家自己動手實踐使用過才能領會,如果想閱讀更多相關內容的文章,歡迎關注創新互聯行業資訊頻道!

本文標題:vue頁面更新patch的
文章出自:http://www.2m8n56k.cn/article28/pshejp.html

成都網站建設公司_創新互聯,為您提供網站設計品牌網站建設軟件開發面包屑導航商城網站營銷型網站建設

廣告

聲明:本網站發布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯系客服。電話:028-86922220;郵箱:[email protected]。內容未經允許不得轉載,或轉載時需注明來源: 創新互聯

綿陽服務器托管
主站蜘蛛池模板: 国产高清美女一级a毛片久久 | 成人免费看黄网址 | 九一色视频 | 性色欧美xo影院 | 色偷偷888欧美精品久久久 | 一级毛片视频播放 | 精品综合久久久久久蜜月 | 色综合九九 | 一区国严二区亚洲三区 | 韩国精品视频在线观看 | 免费一级毛片在线播放放视频 | 欧美精品一二三区 | 亚洲精品视频在线看 | 日韩免费高清一级毛片在线 | 免费人成激情视频在线观看冫 | 欧美成一级 | 日本黄页网站免费大全 | 日本午夜高清视频 | 91在线精品亚洲一区二区 | 亚洲国产成a人v在线观看 | 欧美.亚洲.日本一区二区三区 | 国产一区二区三区在线观看免费 | 成人免费观看国产高清 | 日韩美女专区中文字幕 | 国产成人精品福利网站在线观看 | 欧美曰韩一区二区三区 | 欧美深夜影院 | 国产视频二 | 国内视频一区二区 | 麻豆国产96在线 | 中国 | 女人张开腿让男人捅视频 | 99精品视频在线视频免费观看 | 欧美一级毛片一级毛片 | 韩国毛片 | www.亚洲精品 | 一区二区三区欧美视频 | 国产成人www免费人成看片 | 热久久在线观看 | 久久视频免费在线观看 | 国产成人理在线观看视频 | 男人的天堂久久精品激情 |