目錄
一、Key是什麼
場景背後的邏輯
二、設定key與不設定key區別##舉個範例:
其實不然,文檔中也明確表示 
三、原理分析
首頁 web前端 Vue.js vue中什麼是Key?設定key與不設定有什麼差別?

vue中什麼是Key?設定key與不設定有什麼差別?

May 19, 2022 pm 09:09 PM
vue vue.js

vue中什麼是Key?以下這篇文章跟大家介紹一下vue中key的原理,聊聊設定key與不設定key的差別,希望對大家有幫助!

vue中什麼是Key?設定key與不設定有什麼差別?

一、Key是什麼

#開始之前,我們先還原兩個實際工作場景

  • #當我們在使用v-for時,需要為單元加上key

<ul>
    <li v-for="item in items" :key="item.id">...</li>
</ul>
登入後複製
  • #用 new Date()產生的時間戳記作為key,手動強制觸發重新渲染

<Comp :key="+new Date()" />
登入後複製

那麼這背後的邏輯是什麼,key的作用又是什麼?

一句話來講

key是給每一個vnode的唯一id,也是diff的一種最佳化策略,可以根據key,更準確, 更快的找到對應的vnode節點。 (學習影片分享:vue影片教學

場景背後的邏輯

當我們在使用v-for 時,需要為單元加上key

  • 如果不用key,Vue會採用就地複地原則:最小化element的移動,並且會嘗試盡最大程度在同適當的地方對相同類型的element,做patch或reuse。
  • 如果使用了key,Vue會根據keys的順序記錄element,曾經擁有了key的element如果不再出現的話,會被直接remove或者destoryed
##用

new Date()產生的時間戳記作為key,手動強制觸發重新渲染

    當擁有新值的rerender作為key時,擁有了新key的Comp出現了,那麼舊key Comp會被移除,新key Comp觸發渲染

二、設定key與不設定key區別##舉個範例:

建立一個實例,2秒後往

items
陣列插入資料<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class='brush:php;toolbar:false;'>&lt;body&gt; &lt;div id=&quot;demo&quot;&gt; &lt;p v-for=&quot;item in items&quot; :key=&quot;item&quot;&gt;{{item}}&lt;/p&gt; &lt;/div&gt; &lt;script src=&quot;../../dist/vue.js&quot;&gt;&lt;/script&gt; &lt;script&gt; // 创建实例 const app = new Vue({ el: &amp;#39;#demo&amp;#39;, data: { items: [&amp;#39;a&amp;#39;, &amp;#39;b&amp;#39;, &amp;#39;c&amp;#39;, &amp;#39;d&amp;#39;, &amp;#39;e&amp;#39;] }, mounted () { setTimeout(() =&gt; { this.items.splice(2, 0, &amp;#39;f&amp;#39;) // }, 2000); }, }); &lt;/script&gt; &lt;/body&gt;</pre><div class="contentsignin">登入後複製</div></div>在不使用

key

的情況,vue會進行這樣的操作:

vue中什麼是Key?設定key與不設定有什麼差別?分析下整體流程:

比較A,A,相同類型的節點,進行
    patch
  • ,但資料相同,不發生dom操作比較B,B,相同類型的節點,進行
  • patch
  • ,但資料相同,不發生dom操作比較C,F,相同類型的節點,進行
  • patch
  • ,資料不同,發生dom操作#比較D,C,相同類型的節點,進行
  • patch
  • ,資料不同,發生dom操作比較E,D,相同類型的節點,進行
  • patch
  • ,資料不同,發生dom操作循環結束,將E插入到
  • DOM
  • #一共發生了3次更新,1次插入操作

在使用

key

的情況:vue會進行這樣的操作:

比較A,A,相同類型的節點,進行
    patch
  • ,但資料相同,不發生dom操作比較B,B,相同類型的節點,進行
  • patch
  • ,但資料相同,不發生dom操作比較C,F,不相同類型的節點
  • 比較E、E,相同類型的節點,進行
      patch
    • ,但資料相同,不發生dom操作
    比較D、D,相同類型的節點,進行
  • patch
  • ,但資料相同,不發生dom操作比較C、C,相同類型的節點,進行
  • patch
  • ,但資料相同,不發生dom操作循環結束,將F插入到C之前
  • 一共發生了0次更新,1次插入操作

透過上面兩個小例子,可見設定

key

能夠大幅減少對頁面的DOM操作,提高了diff效率

#設定key值一定能提高diff效率嗎?

其實不然,文檔中也明確表示 

當Vue.js 用v-for 正在更新已渲染過的元素列表時,它默認用“就地復用”策略。如果資料項目的順序被改變,Vue 將不會移動DOM 元素來匹配資料項目的順序, 而是簡單地複用此處每個元素,並且確保它在特定索引下顯示已被渲染過的每個元素 

這個預設的模式是高效率的,但只適用於不依賴子元件狀態或暫時DOM 狀態(例如:表單輸入值) 的清單渲染輸出 

建議盡可能在使用 

v-for

 時提供 key,除非遍歷輸出的DOM 內容非常簡單,或是刻意依賴預設行為以取得效能上的提升<h2 id="strong-三-原理分析-strong"><strong>三、原理分析</strong></h2><p>源码位置:core/vdom/patch.js </p><p>里判断是否为同一个<code>key,首先判断的是key值是否相等如果没有设置key,那么keyundefined,这时候undefined是恒等于undefined

function sameVnode (a, b) {
    return (
        a.key === b.key && (
            (
                a.tag === b.tag &&
                a.isComment === b.isComment &&
                isDef(a.data) === isDef(b.data) &&
                sameInputType(a, b)
            ) || (
                isTrue(a.isAsyncPlaceholder) &&
                a.asyncFactory === b.asyncFactory &&
                isUndef(b.asyncFactory.error)
            )
        )
    )
}
登入後複製

updateChildren方法中会对新旧vnode进行diff,然后将比对出的结果用来更新真实的DOM

function updateChildren (parentElm, oldCh, newCh, insertedVnodeQueue, removeOnly) {
    ...
    while (oldStartIdx <= oldEndIdx && newStartIdx <= newEndIdx) {
        if (isUndef(oldStartVnode)) {
            ...
        } else if (isUndef(oldEndVnode)) {
            ...
        } else if (sameVnode(oldStartVnode, newStartVnode)) {
            ...
        } else if (sameVnode(oldEndVnode, newEndVnode)) {
            ...
        } else if (sameVnode(oldStartVnode, newEndVnode)) { // Vnode moved right
            ...
        } else if (sameVnode(oldEndVnode, newStartVnode)) { // Vnode moved left
            ...
        } else {
            if (isUndef(oldKeyToIdx)) oldKeyToIdx = createKeyToOldIdx(oldCh, oldStartIdx, oldEndIdx)
            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]
        }
    }
    ...
}
登入後複製

(学习视频分享:web前端开发编程基础视频

以上是vue中什麼是Key?設定key與不設定有什麼差別?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
1 個月前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
1 個月前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您聽不到任何人,如何修復音頻
1 個月前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.聊天命令以及如何使用它們
1 個月前 By 尊渡假赌尊渡假赌尊渡假赌

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

vue.js vs.反應:特定於項目的考慮因素 vue.js vs.反應:特定於項目的考慮因素 Apr 09, 2025 am 12:01 AM

Vue.js適合中小型項目和快速迭代,React適用於大型複雜應用。 1)Vue.js易於上手,適用於團隊經驗不足或項目規模較小的情況。 2)React的生態系統更豐富,適合有高性能需求和復雜功能需求的項目。

vue怎麼給按鈕添加函數 vue怎麼給按鈕添加函數 Apr 08, 2025 am 08:51 AM

可以通過以下步驟為 Vue 按鈕添加函數:將 HTML 模板中的按鈕綁定到一個方法。在 Vue 實例中定義該方法並編寫函數邏輯。

vue中怎麼用bootstrap vue中怎麼用bootstrap Apr 07, 2025 pm 11:33 PM

在 Vue.js 中使用 Bootstrap 分為五個步驟:安裝 Bootstrap。在 main.js 中導入 Bootstrap。直接在模板中使用 Bootstrap 組件。可選:自定義樣式。可選:使用插件。

vue.js怎麼引用js文件 vue.js怎麼引用js文件 Apr 07, 2025 pm 11:27 PM

在 Vue.js 中引用 JS 文件的方法有三種:直接使用 &lt;script&gt; 標籤指定路徑;利用 mounted() 生命週期鉤子動態導入;通過 Vuex 狀態管理庫進行導入。

vue中的watch怎麼用 vue中的watch怎麼用 Apr 07, 2025 pm 11:36 PM

Vue.js 中的 watch 選項允許開發者監聽特定數據的變化。當數據發生變化時,watch 會觸發一個回調函數,用於執行更新視圖或其他任務。其配置選項包括 immediate,用於指定是否立即執行回調,以及 deep,用於指定是否遞歸監聽對像或數組的更改。

vue返回上一頁的方法 vue返回上一頁的方法 Apr 07, 2025 pm 11:30 PM

Vue.js 返回上一頁有四種方法:$router.go(-1)$router.back()使用 &lt;router-link to=&quot;/&quot;&gt; 組件window.history.back(),方法選擇取決於場景。

vue多頁面開發是啥意思 vue多頁面開發是啥意思 Apr 07, 2025 pm 11:57 PM

Vue 多頁面開發是一種使用 Vue.js 框架構建應用程序的方法,其中應用程序被劃分為獨立的頁面:代碼維護性:將應用程序拆分為多個頁面可以使代碼更易於管理和維護。模塊化:每個頁面都可以作為獨立的模塊,便於重用和替換。路由簡單:頁面之間的導航可以通過簡單的路由配置來管理。 SEO 優化:每個頁面都有自己的 URL,這有助於搜索引擎優化。

怎樣查詢vue的版本 怎樣查詢vue的版本 Apr 07, 2025 pm 11:24 PM

可以通過以下方法查詢 Vue 版本:使用 Vue Devtools 在瀏覽器的控制台中查看“Vue”選項卡。使用 npm 運行“npm list -g vue”命令。在 package.json 文件的“dependencies”對像中查找 Vue 項。對於 Vue CLI 項目,運行“vue --version”命令。檢查 HTML 文件中引用 Vue 文件的 &lt;script&gt; 標籤中的版本信息。

See all articles