最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

深入了解Vue2中的的雙端diff算法

 更新時(shí)間:2023年02月08日 10:53:52   作者:mick  
雙端Diff在可以解決更多簡單Diff算法處理不了的場景,且比簡單Diff算法性能更好。本文主要來和大家詳細(xì)講講Vue2中的雙端diff算法的實(shí)現(xiàn)與使用,需要的可以參考一下

今天又重讀了vue2的核心源碼,主要之前讀vue2源碼的時(shí)候純屬的硬記,或者說純粹的為了應(yīng)付面試,導(dǎo)致我們并沒有去細(xì)品源碼中的精妙之處。如果回頭在重讀源碼的時(shí)候,發(fā)現(xiàn)其中有很多地方是值得我們深入了解的。比如我們今天要看的“雙端diff”。還記得之前就記得雙端diff對比的口訣”頭頭、尾尾、頭尾、尾頭“,具體對比做了啥事,這種對比有什么好處,可以說是一無所知。今天我們就來好好的看看。

patch可以將vnode渲染成真實(shí)的DOM,實(shí)際作用是在現(xiàn)有的DOM進(jìn)行修改來完成更新視圖的目的。

在說“雙端diff”之前,我們先來簡單看看“簡單diff”。

簡單diff算法

更新文本節(jié)點(diǎn)

const oldVNode = {
  type: "div",
  children: [{ type: "p", children: " 1" }],
  children: [{ type: "p", children: " 2" }],
  children: [{ type: "p", children: " 3" }],
};

const newVNode = {
  type: "div",
  children: [{ type: "p", children: " 4" }],
  children: [{ type: "p", children: " 5" }],
  children: [{ type: "p", children: " 6" }],
};

我們知道,操作DOM的性能開銷都比較大,比如我們創(chuàng)建一個(gè)DOM的時(shí)候,會(huì)連帶著創(chuàng)建很多的屬性。如果我們想將oldVNode替換成newVNode,最暴力的解法就是卸載所有舊子節(jié)點(diǎn),掛載所有新的子節(jié)點(diǎn),這樣就會(huì)頻繁的操作dom。但是我們根據(jù)例子發(fā)現(xiàn),如果說節(jié)點(diǎn)都是p標(biāo)簽,只是內(nèi)容發(fā)生了改變,那是不是就只可以直接修改內(nèi)容了,這樣就不需要頻繁的刪除dom,創(chuàng)建dom了。

key的作用

const oldVNode = [{ type: "p" }, { type: "div" }, { type: "span" }];

const newVNode = [{ type: "span" }, { type: "p" }, { type: "div" }];

根據(jù)上面的例子,如果操作DOM的話,則需要將舊子節(jié)點(diǎn)中的標(biāo)簽和新子節(jié)點(diǎn)中的標(biāo)簽進(jìn)行一對一的對比,如果舊子節(jié)點(diǎn)中的{type: 'p'}和新子節(jié)點(diǎn)中的{type: 'span'}不是相同的標(biāo)簽,會(huì)先卸載{type: 'p'},然后再掛載{ type:'span'},這需要執(zhí)行 2 次 DOM 操作。仔細(xì)觀察可以發(fā)現(xiàn),新舊子節(jié)點(diǎn)僅僅是順序不同,這樣就可以通過DOM的移動(dòng)來完成子節(jié)點(diǎn)的更新了。

如果僅僅通過type判斷,那么type相同,內(nèi)容不同呢。比如:

const oldVNode = [
  { type: "p", children: " 1" },
  { type: "p", children: " 2" },
  { type: "p", children: " 3" },
];

const newVNode = [
  { type: "p", children: " 3" },
  { type: "p", children: " 1" },
  { type: "p", children: " 2" },
];

這里我們確實(shí)可以通過移動(dòng)DOM來完成更新,但是我們現(xiàn)在繼續(xù)用type去判斷還能行嗎?肯定不行的,因?yàn)閠ype都是一樣的。這時(shí),我們就需要引入額外的key來作為vnode的標(biāo)識(shí)。

const oldVNode = [
  { type: "p", children: " 1", key: " 1" },
  { type: "p", children: " 2", key: " 2" },
  { type: "p", children: " 3", key: " 3" },
];

const newVNode = [
  { type: "p", children: " 3", key: " 3" },
  { type: "p", children: " 1", key: " 1" },
  { type: "p", children: " 2", key: " 2" },
];

這時(shí)我們找到需要移動(dòng)的元素更新即可了。

如何移動(dòng)呢

比如我們有三個(gè)節(jié)點(diǎn),我們希望移動(dòng)將老的節(jié)點(diǎn)更新成為新的節(jié)點(diǎn),此時(shí)我們需要一個(gè)變量lastIndex為0來記錄,只要當(dāng)前的節(jié)點(diǎn)索引小于lastIndex,則說明此節(jié)點(diǎn)需要移動(dòng)。如果當(dāng)前的索引大于等于lastIndex,則說明此節(jié)點(diǎn)不需要移動(dòng),并且將當(dāng)前節(jié)點(diǎn)的索引值賦值給lastIndex。

let lastIndex = 0;
for (let i = 0; i < newChildren.length; i++) {
  const newVNode = newChildren[i];
  // 遍歷舊的children
  // 在第一場循環(huán)中定義變量find,代表是否在舊的一組子節(jié)點(diǎn)中找到可復(fù)用的節(jié)點(diǎn)
  let find = false;
  for (let j = 0; j < oldChildren.length; j++) {
    const oldVNode = oldChildren[j];
    // 如果找到具有相同的key值得兩個(gè)節(jié)點(diǎn),說明可以復(fù)用,仍然需要調(diào)用patch函數(shù)更新
    if (newVNode.key === oldVNode.key) {
      patch(oldVNode, newVNode, container);
      if (j < lastIndex) {
        // 如果當(dāng)前找到的節(jié)點(diǎn)在舊children中的索引小于最大索引值lastIndex
        // 說明該節(jié)點(diǎn)對應(yīng)的真實(shí)DOM需要移動(dòng)

        // 先獲取newVnode的前一個(gè)vnode, prevVNode
        const prevVNode = newChildren[i - 1];
        if (prevVNode) {
          // 由于我們要將newVnode對應(yīng)的真實(shí)DOM移動(dòng)到prevVNode所對應(yīng)真實(shí)DOM后面
          // 所以我們需要獲取prevVNode所對應(yīng)真實(shí)DOM的下一個(gè)兄弟節(jié)點(diǎn),并將其作為錨點(diǎn)
          const anchor = prevVNode.el.nextSibling;

          // 調(diào)用insert方法將newVNode對應(yīng)的真實(shí)DOM插入到錨點(diǎn)元素前面
          // 也就是preVNode對應(yīng)真實(shí)DOM的后面
          insert(newVNode.el, container, anchor);
        }
      } else {
        // 如果當(dāng)前找到的節(jié)點(diǎn)在舊children中的索引不小于最大索引值
        // 則更新lastIndex的值
        lastIndex = j;
      }
      break;
    }

  }
}

以上是一個(gè)簡單的demo實(shí)現(xiàn),則發(fā)現(xiàn)需要對舊子節(jié)點(diǎn)移動(dòng)兩次才能更新成新的子節(jié)點(diǎn)。

但是我們仔細(xì)觀察發(fā)現(xiàn),其實(shí)只需要將C移動(dòng)到最前面,這一步就可以實(shí)現(xiàn)了。此時(shí)我們就需要雙端diff算法

雙端diff算法

雙端diff算法是一種同時(shí)對新舊兩組子節(jié)點(diǎn)的兩個(gè)斷點(diǎn)進(jìn)行對比的算法。所以我們需要四個(gè)索引值,分別指向新舊兩組子節(jié)點(diǎn)的端點(diǎn)。

比較方式

在雙端diff算法比較中,每一輪比較都會(huì)分成4個(gè)步驟

  • 第一步:舊子節(jié)點(diǎn)的開始節(jié)點(diǎn)和新子節(jié)點(diǎn)的開始節(jié)點(diǎn)進(jìn)行對比,看看他們是否相同。根據(jù)他們的標(biāo)簽和key判斷,兩個(gè)節(jié)點(diǎn)不相同,所以什么都不做
  • 第二步:舊子節(jié)點(diǎn)的結(jié)束節(jié)點(diǎn)和新子節(jié)點(diǎn)的結(jié)束節(jié)點(diǎn)進(jìn)行對比,看看他們是否相同。根據(jù)他們的標(biāo)簽和key判斷,兩個(gè)節(jié)點(diǎn)不相同,所以什么都不做
  • 第三步:舊子節(jié)點(diǎn)的開始節(jié)點(diǎn)和新子節(jié)點(diǎn)的結(jié)束節(jié)點(diǎn)進(jìn)行對比,看看他們是否相同。根據(jù)他們的標(biāo)簽和key判斷,兩個(gè)節(jié)點(diǎn)不相同,所以什么都不做
  • 第四步:舊子節(jié)點(diǎn)的結(jié)束節(jié)點(diǎn)和新子節(jié)點(diǎn)的開始節(jié)點(diǎn)進(jìn)行對比,看看他們是否相同。根據(jù)他們的標(biāo)簽和key判斷,兩個(gè)節(jié)點(diǎn)相同,說明節(jié)點(diǎn)可以復(fù)用,此時(shí)節(jié)點(diǎn)需要通過移動(dòng)來更新。

那又該怎么移動(dòng)呢?

根據(jù)對比我們發(fā)現(xiàn),我們在第四步是將舊子節(jié)點(diǎn)的結(jié)束節(jié)點(diǎn)和新子節(jié)點(diǎn)的開始節(jié)點(diǎn)進(jìn)行對比,發(fā)現(xiàn)節(jié)點(diǎn)可復(fù)用。說明節(jié)點(diǎn)’D‘在舊子節(jié)點(diǎn)中是最后一個(gè)節(jié)點(diǎn),在新子節(jié)點(diǎn)中是第一個(gè)節(jié)點(diǎn),而我們要操作的是老節(jié)點(diǎn)也就是現(xiàn)有節(jié)點(diǎn),來實(shí)現(xiàn)視圖的更新。所以我們只需要將索引 oldEndIdx 指向的虛擬節(jié)點(diǎn)所對應(yīng)的真實(shí)DOM 移動(dòng)到索引 oldStartIdx 指向的虛擬節(jié)點(diǎn)所對應(yīng)的真實(shí) DOM前面。我們看下源碼:

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)) { 
        // 老的開始節(jié)點(diǎn) 和 新的開始節(jié)點(diǎn)一樣
       ···
      } else if (sameVnode(oldEndVnode, newEndVnode)) {
        // 老的結(jié)束節(jié)點(diǎn) 和 新的結(jié)束節(jié)點(diǎn)一樣
       ···
      } else if (sameVnode(oldStartVnode, newEndVnode)) { // Vnode moved right
        // 老的開始節(jié)點(diǎn) 和 新的結(jié)束節(jié)點(diǎn)一樣
       ···
      } else if (sameVnode(oldEndVnode, newStartVnode)) { // Vnode moved left
        // 老的結(jié)束節(jié)點(diǎn) 和 新的開始節(jié)點(diǎn)一樣
        patchVnode(oldEndVnode, newStartVnode, insertedVnodeQueue, newCh, newStartIdx)
        // 將老的結(jié)束節(jié)點(diǎn) 塞到 老的新節(jié)點(diǎn)之前
        canMove && nodeOps.insertBefore(parentElm, oldEndVnode.elm, oldStartVnode.elm)
        oldEndVnode = oldCh[--oldEndIdx]
        newStartVnode = newCh[++newStartIdx]
      } else {  // 非理想狀態(tài)下的處理方式
        ···
      }
    } 
  }

從源碼中我們看到執(zhí)行了patchVnode。這個(gè)函數(shù)其實(shí)就是將需要對比的兩個(gè)新老節(jié)點(diǎn)進(jìn)行打補(bǔ)丁,因?yàn)槲覀兇藭r(shí)只能確認(rèn)新老節(jié)點(diǎn)他們的標(biāo)簽和key是一樣的,并不代表他們的內(nèi)容一樣,所以需要先更新節(jié)點(diǎn)的內(nèi)容,然后再修改節(jié)點(diǎn)的位置。最后我們只需要以頭部元素oldStartVNode.elm 作為錨點(diǎn),將尾部元素 oldEndVNode.elm 移動(dòng)到錨點(diǎn)前面即可。最后涉及的兩個(gè)索引分別是oldEndIdxnewStartIdx,所以我們需要更新兩者的值,讓它們各自朝正確的方向前進(jìn)一步,并指向下一個(gè)節(jié)點(diǎn)。

接著繼續(xù)進(jìn)行下一輪對比

還是按照我們上面說的那4步對比。此時(shí),當(dāng)我們執(zhí)行第二步對比的時(shí)候,發(fā)現(xiàn)老的結(jié)束節(jié)點(diǎn)和新的結(jié)束節(jié)點(diǎn)是一樣的。所以就會(huì)執(zhí)行以下操作:

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)) { 
        // 老的開始節(jié)點(diǎn) 和 新的開始節(jié)點(diǎn)一樣
       ···
      } else if (sameVnode(oldEndVnode, newEndVnode)) {
        // 老的結(jié)束節(jié)點(diǎn) 和 新的結(jié)束節(jié)點(diǎn)一樣
        patchVnode(oldEndVnode, newEndVnode, insertedVnodeQueue, newCh, newEndIdx)
        oldEndVnode = oldCh[--oldEndIdx]
        newEndVnode = newCh[--newEndIdx]
      } else if (sameVnode(oldStartVnode, newEndVnode)) { // Vnode moved right
        // 老的開始節(jié)點(diǎn) 和 新的結(jié)束節(jié)點(diǎn)一樣
       ···
      } else if (sameVnode(oldEndVnode, newStartVnode)) { // Vnode moved left
        // 老的結(jié)束節(jié)點(diǎn) 和 新的開始節(jié)點(diǎn)一樣
       ···
      } else {  // 非理想狀態(tài)下的處理方式
        ···
      }
    } 
}

這里就只需要通過patchVnode更新新舊子節(jié)點(diǎn)的內(nèi)容,然后更新oldEndIdxnewStartIdx,讓它們各自朝正確的方向前進(jìn)一步,并指向下一個(gè)節(jié)點(diǎn)。

接著繼續(xù)進(jìn)行下一輪對比

當(dāng)對比到第三步的時(shí)候,發(fā)現(xiàn)老的開始節(jié)點(diǎn)和新的結(jié)束節(jié)點(diǎn)一樣

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)) { 
        // 老的開始節(jié)點(diǎn) 和 新的開始節(jié)點(diǎn)一樣
       ···
      } else if (sameVnode(oldEndVnode, newEndVnode)) {
        // 老的結(jié)束節(jié)點(diǎn) 和 新的結(jié)束節(jié)點(diǎn)一樣
       ···
      } else if (sameVnode(oldStartVnode, newEndVnode)) { // Vnode moved right
        // 老的開始節(jié)點(diǎn) 和 新的結(jié)束節(jié)點(diǎn)一樣
        patchVnode(oldStartVnode, newEndVnode, insertedVnodeQueue, newCh, newEndIdx)
        // 將老的開始節(jié)點(diǎn) 塞到 老的結(jié)束節(jié)點(diǎn)后面
        canMove && nodeOps.insertBefore(parentElm, oldStartVnode.elm, nodeOps.nextSibling(oldEndVnode.elm))
        oldStartVnode = oldCh[++oldStartIdx]
        newEndVnode = newCh[--newEndIdx]
      } else if (sameVnode(oldEndVnode, newStartVnode)) { // Vnode moved left
        // 老的結(jié)束節(jié)點(diǎn) 和 新的開始節(jié)點(diǎn)一樣
       ···
      } else {  // 非理想狀態(tài)下的處理方式
        ···
      }
    } 
}

首先通過patchVnode更新新舊子節(jié)點(diǎn)的內(nèi)容。舊的一組子節(jié)點(diǎn)的頭部節(jié)點(diǎn)與新的一組子節(jié)點(diǎn)的尾部節(jié)點(diǎn)匹配,則說明該舊節(jié)點(diǎn)所對應(yīng)的真實(shí) DOM 節(jié)點(diǎn)需要移動(dòng)到尾部。因此,我們需要獲取當(dāng)前尾部節(jié)點(diǎn)的下一個(gè)兄弟節(jié)點(diǎn)作為錨點(diǎn),即 oldEndVNode.el.nextSibling。最后,更新相關(guān)索引到下一個(gè)位置。

接著繼續(xù)進(jìn)行下一輪對比

這里就只需要通過patchVnode更新新舊子節(jié)點(diǎn)的內(nèi)容,發(fā)現(xiàn)內(nèi)容一樣什么都不做,然后更新oldEndIdxnewStartIdx,讓它們各自朝正確的方向前進(jìn)一步,并指向下一個(gè)節(jié)點(diǎn),這就退出了循環(huán)。

以上是理想情況下的處理方式,當(dāng)然還有非理想情況下的處理方式

非理想情況的處理方式

比如:

此時(shí)我們發(fā)現(xiàn)之前說的情況都無法命中,所以我們只能通過增加額外的步驟去處理。由于我們都是對比的頭部和尾部,既然都無法命中,那就試試非頭部、非尾部節(jié)點(diǎn)能否復(fù)用。此時(shí)我們可以發(fā)現(xiàn)新子節(jié)點(diǎn)中頭部節(jié)點(diǎn)和舊子節(jié)點(diǎn)中的第二個(gè)節(jié)點(diǎn)是可以復(fù)用的,所以只需要將舊子節(jié)點(diǎn)中的第二個(gè)節(jié)點(diǎn)移動(dòng)到當(dāng)前舊子節(jié)點(diǎn)的頭部即可。

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)) { 
        // 老的開始節(jié)點(diǎn) 和 新的開始節(jié)點(diǎn)一樣
       ···
      } else if (sameVnode(oldEndVnode, newEndVnode)) {
        // 老的結(jié)束節(jié)點(diǎn) 和 新的結(jié)束節(jié)點(diǎn)一樣
       ···
      } else if (sameVnode(oldStartVnode, newEndVnode)) { // Vnode moved right
        // 老的開始節(jié)點(diǎn) 和 新的結(jié)束節(jié)點(diǎn)一樣
       ···
      } else if (sameVnode(oldEndVnode, newStartVnode)) { // Vnode moved left
        // 老的結(jié)束節(jié)點(diǎn) 和 新的開始節(jié)點(diǎn)一樣
       ···
      } else {  // 非理想狀態(tài)下的處理方式
        if (isUndef(oldKeyToIdx)) oldKeyToIdx = createKeyToOldIdx(oldCh, oldStartIdx, oldEndIdx)
        idxInOld = isDef(newStartVnode.key)
          ? oldKeyToIdx[newStartVnode.key]
          // 新的一組子節(jié)點(diǎn)的頭部 去 舊的一組節(jié)點(diǎn)中尋找
          : findIdxInOld(newStartVnode, oldCh, oldStartIdx, oldEndIdx)
        if (isUndef(idxInOld)) { // New element
          createElm(newStartVnode, insertedVnodeQueue, parentElm, oldStartVnode.elm, false, newCh, newStartIdx)
        } else {
          // 拿到新節(jié)點(diǎn)頭部 在舊的一組節(jié)點(diǎn)中對應(yīng)的節(jié)點(diǎn)
          vnodeToMove = oldCh[idxInOld]
          if (sameVnode(vnodeToMove, newStartVnode)) { // 如果是相同的節(jié)點(diǎn) 則patch 
            patchVnode(vnodeToMove, newStartVnode, insertedVnodeQueue, newCh, newStartIdx)
            // 將老的節(jié)點(diǎn)中對應(yīng)的設(shè)置為undefined
            oldCh[idxInOld] = undefined
            // 移動(dòng)節(jié)點(diǎn) 
            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]
      }
    } 
}

首先那新的子節(jié)點(diǎn)的頭部去舊的一組子節(jié)點(diǎn)中尋找,如果沒有找到,說明這個(gè)節(jié)點(diǎn)是一個(gè)新的節(jié)點(diǎn),則直接創(chuàng)建節(jié)點(diǎn)。如果找到了,通過索引去獲取對應(yīng)的舊節(jié)點(diǎn)的信息,如果節(jié)點(diǎn)可復(fù)用,則需要將當(dāng)前舊節(jié)點(diǎn)移動(dòng)到頭部即可。最后更新新節(jié)點(diǎn)的開始節(jié)點(diǎn)的索引位置。

到此這篇關(guān)于深入了解Vue2中的的雙端diff算法的文章就介紹到這了,更多相關(guān)Vue雙端diff算法內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 基于Vue3實(shí)現(xiàn)一個(gè)簡單的方位動(dòng)畫

    基于Vue3實(shí)現(xiàn)一個(gè)簡單的方位動(dòng)畫

    這篇文章主要為大家詳細(xì)介紹了如何基于Vue3實(shí)現(xiàn)一個(gè)簡單的方位動(dòng)畫,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2024-02-02
  • vue+tp5實(shí)現(xiàn)簡單登錄功能

    vue+tp5實(shí)現(xiàn)簡單登錄功能

    這篇文章主要為大家詳細(xì)介紹了vue+tp5實(shí)現(xiàn)簡單登錄功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-11-11
  • vue2項(xiàng)目中全局封裝axios問題

    vue2項(xiàng)目中全局封裝axios問題

    這篇文章主要介紹了vue2項(xiàng)目中全局封裝axios問題,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-10-10
  • vue中v-if和v-for一起使用的弊端及解決辦法(同時(shí)使用 v-if 和 v-for不推薦)

    vue中v-if和v-for一起使用的弊端及解決辦法(同時(shí)使用 v-if 和 v-for不

    當(dāng) v-if 和 v-for 同時(shí)存在于一個(gè)元素上的時(shí)候,v-if 會(huì)首先被執(zhí)行,這篇文章主要介紹了vue中v-if和v-for一起使用的弊端及解決辦法,需要的朋友可以參考下
    2023-07-07
  • 詳解前后端分離之VueJS前端

    詳解前后端分離之VueJS前端

    本篇文章主要介紹了詳解前后端分離之VueJS前端,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-05-05
  • vue項(xiàng)目實(shí)例中用query傳參如何實(shí)現(xiàn)跳轉(zhuǎn)效果

    vue項(xiàng)目實(shí)例中用query傳參如何實(shí)現(xiàn)跳轉(zhuǎn)效果

    這篇文章主要介紹了vue項(xiàng)目實(shí)例中用query傳參如何實(shí)現(xiàn)跳轉(zhuǎn)效果,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-10-10
  • 記VUE3+TS獲取組件類型的方法踩坑及解決

    記VUE3+TS獲取組件類型的方法踩坑及解決

    這篇文章主要介紹了VUE3+TS獲取組件類型的方法踩坑及解決方案,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-03-03
  • Vue Computed中g(shù)et和set的用法及Computed與watch的區(qū)別

    Vue Computed中g(shù)et和set的用法及Computed與watch的區(qū)別

    這篇文章主要介紹了Vue Computed中g(shù)et和set的用法及Computed與watch的區(qū)別,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-11-11
  • vue項(xiàng)目在IE瀏覽器下運(yùn)行空白問題及解決

    vue項(xiàng)目在IE瀏覽器下運(yùn)行空白問題及解決

    IE11瀏覽器無法解析ES6語法導(dǎo)致Vue項(xiàng)目在IE11下顯示空白,解決方法包括安裝babel-polyfill,并在項(xiàng)目的main.js文件中引入babel-polyfill,此外,js-base64版本3及以上不兼容IE11,解決辦法是使用版本3以下的js-base64,這些措施可以幫助兼容IE11,確保項(xiàng)目正常運(yùn)行
    2024-09-09
  • Vue中mixins混入的介紹和使用詳解

    Vue中mixins混入的介紹和使用詳解

    mixins(混入)是一種分發(fā)?Vue?組件中可復(fù)用功能的非常靈活的方式,這篇文章主要為大家介紹了mixins混入的介紹和使用,需要的可以參考下
    2023-08-08

最新評論

海盐县| 桐梓县| 阿坝县| 西贡区| 泰宁县| 利辛县| 无棣县| 斗六市| 青铜峡市| 乌兰县| 元江| 敦煌市| 兴和县| 龙井市| 江西省| 武邑县| 洪泽县| 华池县| 泸溪县| 奇台县| 镇康县| 修水县| 井研县| 静宁县| 自治县| 余江县| 兴业县| 宜春市| 江西省| 正宁县| 德庆县| 梅河口市| 柏乡县| 屯留县| 东乌珠穆沁旗| 正安县| 梁河县| 哈密市| 湘潭县| 安康市| 呼图壁县|