欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

一文詳解Vue?的雙端?diff?算法

 更新時(shí)間:2022年06月30日 10:28:41   作者:??zxg_神說(shuō)要有光????  
這篇文章主要介紹了一文詳解Vue?的雙端?diff?算法,diff?算法是渲染器中最復(fù)雜的部分,也是面試的熱點(diǎn)問(wèn)題。今天我們就通過(guò)?Vue?的?diff?算法來(lái)探究下diff?算法吧

前言

Vue 和 React 都是基于 vdom 的前端框架,組件渲染會(huì)返回 vdom,渲染器再把 vdom 通過(guò)增刪改的 api 同步到 dom。

當(dāng)再次渲染時(shí),會(huì)產(chǎn)生新的 vdom,渲染器會(huì)對(duì)比兩棵 vdom 樹,對(duì)有差異的部分通過(guò)增刪改的 api 更新到 dom。

這里對(duì)比兩棵 vdom 樹,找到有差異的部分的算法,就叫做 diff 算法。

diff 算法

我們知道,兩棵樹做 diff,復(fù)雜度是 O(n^3) 的,因?yàn)槊總€(gè)節(jié)點(diǎn)都要去和另一棵樹的全部節(jié)點(diǎn)對(duì)比一次,這就是 n 了,如果找到有變化的節(jié)點(diǎn),執(zhí)行插入、刪除、修改也是 n 的復(fù)雜度。所有的節(jié)點(diǎn)都是這樣,再乘以 n,所以是 O(n * n * n) 的復(fù)雜度。

這樣的復(fù)雜度對(duì)于前端框架來(lái)說(shuō)是不可接受的,這意味著 1000 個(gè)節(jié)點(diǎn),渲染一次就要處理 1000 * 1000 * 1000,一共 10 億次。

所以前端框架的 diff 約定了兩種處理原則:只做同層的對(duì)比,type 變了就不再對(duì)比子節(jié)點(diǎn)。

因?yàn)?dom 節(jié)點(diǎn)做跨層級(jí)移動(dòng)的情況還是比較少的,一般情況下都是同一層級(jí)的 dom 的增刪改。

這樣只要遍歷一遍,對(duì)比一下 type 就行了,是 O(n) 的復(fù)雜度,而且 type 變了就不再對(duì)比子節(jié)點(diǎn),能省下一大片節(jié)點(diǎn)的遍歷。另外,因?yàn)?vdom 中記錄了關(guān)聯(lián)的 dom 節(jié)點(diǎn),執(zhí)行 dom 的增刪改也不需要遍歷,是 O(1)的,整體的 diff 算法復(fù)雜度就是 O(n) 的復(fù)雜度。

1000 個(gè)節(jié)點(diǎn)渲染一次最多對(duì)比 1000 次,這樣的復(fù)雜度就是可接受的范圍了。但是這樣的算法雖然復(fù)雜度低了,卻還是存在問(wèn)題的。

比如一組節(jié)點(diǎn),假設(shè)有 5 個(gè),類型是 ABCDE,下次渲染出來(lái)的是 EABCD,這時(shí)候逐一對(duì)比,發(fā)現(xiàn) type 不一樣,就會(huì)重新渲染這 5 個(gè)節(jié)點(diǎn)。

而且根據(jù) type 不同就不再對(duì)比子節(jié)點(diǎn)的原則,如果這些節(jié)點(diǎn)有子節(jié)點(diǎn),也會(huì)重新渲染。dom 操作是比較慢的,這樣雖然 diff 的算法復(fù)雜度是低了,重新渲染的性能也不高。

所以,diff 算法除了考慮本身的時(shí)間復(fù)雜度之外,還要考慮一個(gè)因素:dom 操作的次數(shù)。

上面那個(gè)例子的 ABCDE 變?yōu)?EABCD,很明顯只需要移動(dòng)一下 E 就行了,根本不用創(chuàng)建新元素。

但是怎么對(duì)比出是同個(gè)節(jié)點(diǎn)發(fā)生了移動(dòng)呢?

判斷 type 么? 那不行,同 type 的節(jié)點(diǎn)可能很多,區(qū)分不出來(lái)的。最好每個(gè)節(jié)點(diǎn)都是有唯一的標(biāo)識(shí)。

所以當(dāng)渲染一組節(jié)點(diǎn)的時(shí)候,前端框架會(huì)讓開(kāi)發(fā)者指定 key,通過(guò) key 來(lái)判斷是不是有點(diǎn)節(jié)點(diǎn)只是發(fā)生了移動(dòng),從而直接復(fù)用。這樣,diff 算法處理一組節(jié)點(diǎn)的對(duì)比的時(shí)候,就要根據(jù) key 來(lái)再做一次算法的優(yōu)化。我們會(huì)把基于 key 的兩組節(jié)點(diǎn)的 diff 算法叫做多節(jié)點(diǎn) diff 算法,它是整個(gè) vdom 的 diff 算法的一部分。

接下來(lái)我們來(lái)學(xué)習(xí)一下多節(jié)點(diǎn) diff 算法:

簡(jiǎn)單 diff

假設(shè)渲染 ABCD 一組節(jié)點(diǎn),再次渲染是 DCAB,這時(shí)候怎么處理呢?

多節(jié)點(diǎn) diff 算法的目的是為了盡量復(fù)用節(jié)點(diǎn),通過(guò)移動(dòng)節(jié)點(diǎn)代替創(chuàng)建。

所以新 vnode 數(shù)組的每個(gè)節(jié)點(diǎn)我們都要找下在舊 vnode 數(shù)組中有沒(méi)有對(duì)應(yīng) key 的,有的話就移動(dòng)到新的位置,沒(méi)有的話再創(chuàng)建新的。

也就是這樣的:

const oldChildren = n1.children
const newChildren = n2.children
let lastIndex = 0
// 遍歷新的 children
for (let i = 0; i < newChildren.length; i++) {
    const newVNode = newChildren[i]
    let j = 0
    let find = false
    // 遍歷舊的 children
    for (j; j < oldChildren.length; j++) {
      const oldVNode = oldChildren[j]
      // 如果找到了具有相同 key 值的兩個(gè)節(jié)點(diǎn),則調(diào)用 patch 函數(shù)更新
      if (newVNode.key === oldVNode.key) {
        find = true
        patch(oldVNode, newVNode, container)

        處理移動(dòng)...

        break //跳出循環(huán),處理下一個(gè)節(jié)點(diǎn)
      }
   }
   // 沒(méi)有找到就是新增了
   if (!find) {
      const prevVNode = newChildren[i - 1]
      let anchor = null
      if (prevVNode) {
        anchor = prevVNode.el.nextSibling
      } else {
        anchor = container.firstChild
      }
      patch(null, newVNode, container, anchor)
   }
}

這里的 patch 函數(shù)的作用是更新節(jié)點(diǎn)的屬性,重新設(shè)置事件監(jiān)聽(tīng)器。如果沒(méi)有對(duì)應(yīng)的舊節(jié)點(diǎn)的話,就是插入節(jié)點(diǎn),需要傳入一個(gè)它之后的節(jié)點(diǎn)作為錨點(diǎn) anchor。

我們遍歷處理新的 vnode:

先從舊的 vnode 數(shù)組中查找對(duì)應(yīng)的節(jié)點(diǎn),如果找到了就代表可以復(fù)用,接下來(lái)只要移動(dòng)就好了。如果沒(méi)找到,那就執(zhí)行插入,錨點(diǎn)是上一個(gè)節(jié)點(diǎn)的 nextSibling。

那如果找到了可復(fù)用的節(jié)點(diǎn)之后,那移動(dòng)到哪里呢?其實(shí)新的 vnode 數(shù)組中記錄的順序就是目標(biāo)的順序。所以把對(duì)應(yīng)的節(jié)點(diǎn)按照新 vnode 數(shù)組的順序來(lái)移動(dòng)就好了

const prevVNode = newChildren[i - 1]
if (prevVNode) {
    const anchor = prevVNode.el.nextSibling
    insert(newVNode.el, container, anchor)
}

要插入到 i 的位置,那就要取 i-1 位置的節(jié)點(diǎn)的 nextSibling 做為錨點(diǎn)來(lái)插入當(dāng)前節(jié)點(diǎn)。

但是并不是所有的節(jié)點(diǎn)都需要移動(dòng),比如處理到第二個(gè)新的 vnode,發(fā)現(xiàn)它在舊的 vnode 數(shù)組中的下標(biāo)為 4,說(shuō)明本來(lái)就是在后面了,那就不需要移動(dòng)了。反之,如果是 vnode 查找到的對(duì)應(yīng)的舊的 vnode 在當(dāng)前 index 之前才需要移動(dòng)。

也就是這樣:

let j = 0
let find = false
// 遍歷舊的 children
for (j; j < oldChildren.length; j++) {
    const oldVNode = oldChildren[j]
    // 如果找到了具有相同 key 值的兩個(gè)節(jié)點(diǎn),則調(diào)用 patch 函數(shù)更新之
    if (newVNode.key === oldVNode.key) {
        find = true
        patch(oldVNode, newVNode, container)

        if (j < lastIndex) { // 舊的 vnode 數(shù)組的下標(biāo)在上一個(gè) index 之前,需要移動(dòng)
          const prevVNode = newChildren[i - 1]
          if (prevVNode) {
            const anchor = prevVNode.el.nextSibling
            insert(newVNode.el, container, anchor)
          }
        } else {// 不需要移動(dòng)
          // 更新 lastIndex
          lastIndex = j
        }
        break
    }
}

查找新的 vnode 在舊的 vnode 數(shù)組中的下標(biāo),如果找到了的話,說(shuō)明對(duì)應(yīng)的 dom 就是可以復(fù)用的,先 patch 一下,然后移動(dòng)。

移動(dòng)的話判斷下下標(biāo)是否在 lastIndex 之后,如果本來(lái)就在后面,那就不用移動(dòng),更新下 lastIndex 就行。如果下標(biāo)在 lastIndex 之前,說(shuō)明需要移動(dòng),移動(dòng)到的位置前面分析過(guò)了,就是就是新 vnode 數(shù)組 i-1 的后面。這樣,我們就完成了 dom 節(jié)點(diǎn)的復(fù)用和移動(dòng)。

新的 vnode 數(shù)組全部處理完后,舊的 vnode 數(shù)組可能還剩下一些不再需要的,那就刪除它們:

// 遍歷舊的節(jié)點(diǎn)
for (let i = 0; i < oldChildren.length; i++) {
    const oldVNode = oldChildren[i]
    // 拿著舊 VNode 去新 children 中尋找相同的節(jié)點(diǎn)
    const has = newChildren.find(
      vnode => vnode.key === oldVNode.key
    )
    if (!has) {
      // 如果沒(méi)有找到相同的節(jié)點(diǎn),則移除
      unmount(oldVNode)
    }
}

這樣,我們就完成了兩組 vnode 的 diff 和對(duì)應(yīng) dom 的增刪改。

小結(jié)一下:

diff 算法的目的是根據(jù) key 復(fù)用 dom 節(jié)點(diǎn),通過(guò)移動(dòng)節(jié)點(diǎn)而不是創(chuàng)建新節(jié)點(diǎn)來(lái)減少 dom 操作。

對(duì)于每個(gè)新的 vnode,在舊的 vnode 中根據(jù) key 查找一下,如果沒(méi)查找到,那就新增 dom 節(jié)點(diǎn),如果查找到了,那就可以復(fù)用。

復(fù)用的話要不要移動(dòng)要判斷下下標(biāo),如果下標(biāo)在 lastIndex 之后,就不需要移動(dòng),因?yàn)楸緛?lái)就在后面,反之就需要移動(dòng)。

最后,把舊的 vnode 中在新 vnode 中沒(méi)有的節(jié)點(diǎn)從 dom 樹中刪除。

這就是一個(gè)完整的 diff 算法的實(shí)現(xiàn):

這個(gè) diff 算法我們是從一端逐個(gè)處理的,叫做簡(jiǎn)單 diff 算法。簡(jiǎn)單 diff 算法其實(shí)性能不是最好的,比如舊的 vnode 數(shù)組是 ABCD,新的 vnode 數(shù)組是 DABC,按照簡(jiǎn)單 diff 算法,A、B、C 都需要移動(dòng)。

那怎么優(yōu)化這個(gè)算法呢?從一個(gè)方向順序處理會(huì)有這個(gè)問(wèn)題,那從兩個(gè)方向同時(shí)對(duì)比呢?

這就是雙端 diff 算法:

雙端 diff

簡(jiǎn)單 diff 算法能夠?qū)崿F(xiàn) dom 節(jié)點(diǎn)的復(fù)用,但有的時(shí)候會(huì)做一些沒(méi)必要的移動(dòng)。雙端 diff 算法解決了這個(gè)問(wèn)題,它是從兩端進(jìn)行對(duì)比。

我們需要 4 個(gè)指針,分別指向新舊兩個(gè) vnode 數(shù)組的頭尾:

頭和尾的指針向中間移動(dòng),直到 oldStartIdx <= oldEndIdx 并且 newStartIdx <= newEndIdx,說(shuō)明就處理完了全部的節(jié)點(diǎn)。

每次對(duì)比下兩個(gè)頭指針指向的節(jié)點(diǎn)、兩個(gè)尾指針指向的節(jié)點(diǎn),頭和尾指向的節(jié)點(diǎn),是不是 key是一樣的,也就是可復(fù)用的。如果是可復(fù)用的話就直接用,調(diào)用 patch 更新一下,如果是頭尾這種,還要移動(dòng)下位置。

也就是這樣的:

while (oldStartIdx <= oldEndIdx && newStartIdx <= newEndIdx) {
  if (oldStartVNode.key === newStartVNode.key) { // 頭頭
    patch(oldStartVNode, newStartVNode, container)
    oldStartVNode = oldChildren[++oldStartIdx]
    newStartVNode = newChildren[++newStartIdx]
  } else if (oldEndVNode.key === newEndVNode.key) {//尾尾
    patch(oldEndVNode, newEndVNode, container)
    oldEndVNode = oldChildren[--oldEndIdx]
    newEndVNode = newChildren[--newEndIdx]
  } else if (oldStartVNode.key === newEndVNode.key) {//頭尾,需要移動(dòng)
    patch(oldStartVNode, newEndVNode, container)
    insert(oldStartVNode.el, container, oldEndVNode.el.nextSibling)

    oldStartVNode = oldChildren[++oldStartIdx]
    newEndVNode = newChildren[--newEndIdx]
  } else if (oldEndVNode.key === newStartVNode.key) {//尾頭,需要移動(dòng)
    patch(oldEndVNode, newStartVNode, container)
    insert(oldEndVNode.el, container, oldStartVNode.el)

    oldEndVNode = oldChildren[--oldEndIdx]
    newStartVNode = newChildren[++newStartIdx]
  } else {
    // 頭尾沒(méi)有找到可復(fù)用的節(jié)點(diǎn)
  }
}

頭頭和尾尾的對(duì)比比較簡(jiǎn)單,頭尾和尾頭的對(duì)比還要移動(dòng)下節(jié)點(diǎn)。比如舊 vnode 的頭節(jié)點(diǎn)是新的 vnode 的尾節(jié)點(diǎn),那就要把它移動(dòng)到舊的 vnode 的尾節(jié)點(diǎn)的位置。

也就是:

insert(oldStartVNode.el, container, oldEndVNode.el.nextSibling)

插入節(jié)點(diǎn)的錨點(diǎn)節(jié)點(diǎn)是 oldEndVNode 對(duì)應(yīng)的 dom 節(jié)點(diǎn)的 nextSibling。如果舊 vnode 的尾節(jié)點(diǎn)是新 vnode 的頭結(jié)點(diǎn),那就要把它移動(dòng)到舊 vnode 的頭結(jié)點(diǎn)的位置。

也就是:

insert(oldEndVNode.el, container, oldStartVNode.el)

插入節(jié)點(diǎn)的錨點(diǎn)節(jié)點(diǎn)是 oldStartVNode 對(duì)應(yīng)的 dom 節(jié)點(diǎn)(因?yàn)橐逶谒埃碾p端進(jìn)行對(duì)比,能盡可能的減少節(jié)點(diǎn)移動(dòng)的次數(shù)。

當(dāng)然,還要處理下如果雙端都沒(méi)有可復(fù)用節(jié)點(diǎn)的情況:

如果雙端都沒(méi)有可復(fù)用節(jié)點(diǎn),那就在舊節(jié)點(diǎn)數(shù)組中找,找到了就把它移動(dòng)過(guò)來(lái),并且原位置置為 undefined。沒(méi)找到的話就插入一個(gè)新的節(jié)點(diǎn)。

也就是這樣:

const idxInOld = oldChildren.findIndex(
  node => node.key === newStartVNode.key
)
if (idxInOld > 0) {
  const vnodeToMove = oldChildren[idxInOld]
  patch(vnodeToMove, newStartVNode, container)
  insert(vnodeToMove.el, container, oldStartVNode.el)
  oldChildren[idxInOld] = undefined
} else {
  patch(null, newStartVNode, container, oldStartVNode.el)
}

因?yàn)橛辛艘恍?undefined 的節(jié)點(diǎn),所以要加上空節(jié)點(diǎn)的處理邏輯:

if (!oldStartVNode) {
    oldStartVNode = oldChildren[++oldStartIdx]
} else if (!oldEndVNode) {
    oldEndVNode = newChildren[--oldEndIdx]
}

這樣就完成了節(jié)點(diǎn)的復(fù)用和移動(dòng)的邏輯。那確實(shí)沒(méi)有可復(fù)用的節(jié)點(diǎn)的那些節(jié)點(diǎn)呢?

經(jīng)過(guò)前面的移動(dòng)之后,剩下的節(jié)點(diǎn)都被移動(dòng)到了中間,如果新 vnode 有剩余,那就批量的新增,如果舊 vnode 有剩余那就批量的刪除。因?yàn)榍懊嬉粋€(gè)循環(huán)的判斷條件是 oldStartIdx <= oldEndIdx && newStartIdx <= newEndIdx,這樣如果 old vnode 多了,最后 newStartIdx 會(huì)小于 newEndIdx。如果 new vnode 多了,最后 oldStartIdx 會(huì)小于 oldEndIdx。

所以判斷條件是這樣的:

if (oldEndIdx < oldStartIdx && newStartIdx <= newEndIdx) {
  // 添加新節(jié)點(diǎn)
  for (let i = newStartIdx; i <= newEndIdx; i++) {
    patch(null, newChildren[i], container, oldStartVNode.el)
  }
} else if (newEndIdx < newStartIdx && oldStartIdx <= oldEndIdx) {
  // 移除操作
  for (let i = oldStartIdx; i <= oldEndIdx; i++) {
    unmount(oldChildren[i])
  }
}

這樣就是一個(gè)完整的 diff 算法了,包括查找可復(fù)用節(jié)點(diǎn)和移動(dòng)節(jié)點(diǎn)、新增和刪除節(jié)點(diǎn)。而且因?yàn)閺膬蓚?cè)查找節(jié)點(diǎn),會(huì)比簡(jiǎn)單 diff 算法性能更好一些。

比如 ABCD 到 DABC,簡(jiǎn)單 diff 算法需要移動(dòng) ABC 三個(gè)節(jié)點(diǎn),而雙端 diff 算法只需要移動(dòng) D 一個(gè)節(jié)點(diǎn)。

小結(jié)一下:

雙端 diff 是頭尾指針向中間移動(dòng)的同時(shí),對(duì)比頭頭、尾尾、頭尾、尾頭是否可以復(fù)用,如果可以的話就移動(dòng)對(duì)應(yīng)的 dom 節(jié)點(diǎn)。

如果頭尾沒(méi)找到可復(fù)用節(jié)點(diǎn)就遍歷 vnode 數(shù)組來(lái)查找,然后移動(dòng)對(duì)應(yīng)下標(biāo)的節(jié)點(diǎn)到頭部。最后還剩下舊的 vnode 就批量刪除,剩下新的 vnode 就批量新增。

雙端 diff 算法是 Vue2 采用的 diff 算法,性能還不錯(cuò)。后來(lái),Vue3 又對(duì) diff 算法進(jìn)行了一次升級(jí),叫做快速 diff 算法。這個(gè)后面再講。

總結(jié)

React 和 Vue 都是基于 vdom 的前端框架,組件產(chǎn)生 vdom,渲染器再把 vdom 通過(guò)增刪改的 dom api 更新到 dom。

當(dāng)再次渲染出 vdom 時(shí),就要新舊兩棵 vdom 樹做 diff,只更新變化的 dom 節(jié)點(diǎn)。兩棵樹的 diff 是 O(n^3) 的,時(shí)間復(fù)雜度太高,因此前端框架規(guī)定了只做同層 diff,還有 type 不一樣就認(rèn)為節(jié)點(diǎn)不一樣,不再對(duì)比子節(jié)點(diǎn)。這樣時(shí)間復(fù)雜度一下子就降到了 O(n)。但是對(duì)于多個(gè)子字節(jié)點(diǎn)的 diff 不能粗暴的刪除和新增,要盡量復(fù)用已有的節(jié)點(diǎn),也就是通過(guò)移動(dòng)代替新增。所以多節(jié)點(diǎn)的時(shí)候,要指定 key,然后 diff 算法根據(jù) key 來(lái)查找和復(fù)用節(jié)點(diǎn)。

簡(jiǎn)單 diff 算法是依次根據(jù) key 查找舊節(jié)點(diǎn)的,移動(dòng)的話通過(guò) lastIndex 判斷,大于它就不用動(dòng),小于它才需要移動(dòng)。剩下的節(jié)點(diǎn)再批量刪除和新增。但是簡(jiǎn)單 diff 算法局限性還是比較大的,有些情況下性能并不好,所以 vue2 用的是雙端 diff 算法。

雙端 diff 算法是頭尾指針向中間移動(dòng),分別判斷頭尾節(jié)點(diǎn)是否可以復(fù)用,如果沒(méi)有找到可復(fù)用的節(jié)點(diǎn)再去遍歷查找對(duì)應(yīng)節(jié)點(diǎn)的下標(biāo),然后移動(dòng)。全部處理完之后也要對(duì)剩下的節(jié)點(diǎn)進(jìn)行批量的新增和刪除。其實(shí) diff 算法最重要的就是找到可復(fù)用的節(jié)點(diǎn),然后移動(dòng)到正確的位置。只不過(guò)不同的算法查找順序不一樣。

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

相關(guān)文章

  • vue中本地靜態(tài)圖片的路徑應(yīng)該怎么寫

    vue中本地靜態(tài)圖片的路徑應(yīng)該怎么寫

    這篇文章主要介紹了vue中本地靜態(tài)圖片的路徑應(yīng)該怎么寫,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-10-10
  • vue發(fā)布到nginx下請(qǐng)求后臺(tái)404問(wèn)題及解決

    vue發(fā)布到nginx下請(qǐng)求后臺(tái)404問(wèn)題及解決

    這篇文章主要介紹了vue發(fā)布到nginx下請(qǐng)求后臺(tái)404問(wèn)題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-03-03
  • vue.js實(shí)現(xiàn)條件渲染的實(shí)例代碼

    vue.js實(shí)現(xiàn)條件渲染的實(shí)例代碼

    這篇文章主要介紹了vue.js實(shí)現(xiàn)條件渲染的實(shí)例代碼,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-06-06
  • vue element 中的table動(dòng)態(tài)渲染實(shí)現(xiàn)(動(dòng)態(tài)表頭)

    vue element 中的table動(dòng)態(tài)渲染實(shí)現(xiàn)(動(dòng)態(tài)表頭)

    這篇文章主要介紹了vue element 中的table動(dòng)態(tài)渲染實(shí)現(xiàn)(動(dòng)態(tài)表頭),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-11-11
  • element-plus按需引入后ElMessage與ElLoading在頁(yè)面中的使用

    element-plus按需引入后ElMessage與ElLoading在頁(yè)面中的使用

    這篇文章主要介紹了element-plus按需引入后ElMessage與ElLoading在頁(yè)面中的使用方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-09-09
  • 淺談VUE uni-app 常用API

    淺談VUE uni-app 常用API

    這篇文章主要介紹了uni-app 常用API,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-10-10
  • vue中的el-form表單rule校驗(yàn)問(wèn)題(特殊字符、中文、數(shù)字等)

    vue中的el-form表單rule校驗(yàn)問(wèn)題(特殊字符、中文、數(shù)字等)

    這篇文章主要介紹了vue中的el-form表單rule校驗(yàn)問(wèn)題(特殊字符、中文、數(shù)字等),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-05-05
  • vue項(xiàng)目中使用ts(typescript)入門教程

    vue項(xiàng)目中使用ts(typescript)入門教程

    最近項(xiàng)目需要將原vue項(xiàng)目結(jié)合ts的使用進(jìn)行改造,本文從安裝到vue組件編寫進(jìn)行了說(shuō)明,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-11-11
  • 1分鐘Vue實(shí)現(xiàn)右鍵菜單

    1分鐘Vue實(shí)現(xiàn)右鍵菜單

    今天給大家分享的是,如何在最短的時(shí)候內(nèi)實(shí)現(xiàn)右鍵菜單。高效實(shí)現(xiàn)需求,避免重復(fù)造輪子。感興趣的可以了解一下
    2021-10-10
  • vue.js實(shí)現(xiàn)簡(jiǎn)易折疊面板

    vue.js實(shí)現(xiàn)簡(jiǎn)易折疊面板

    這篇文章主要為大家詳細(xì)介紹了JavaScript實(shí)現(xiàn)簡(jiǎn)易折疊面板,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-10-10

最新評(píng)論