千家信息网

vue中设置key与不设置有什么区别

发表于:2026-10-31 作者:千家信息网编辑
千家信息网最后更新 2026年10月31日,本文小编为大家详细介绍"vue中设置key与不设置有什么区别",内容详细,步骤清晰,细节处理妥当,希望这篇"vue中设置key与不设置有什么区别"文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一
千家信息网最后更新 2026年10月31日vue中设置key与不设置有什么区别

本文小编为大家详细介绍"vue中设置key与不设置有什么区别",内容详细,步骤清晰,细节处理妥当,希望这篇"vue中设置key与不设置有什么区别"文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。

一、Key是什么

开始之前,我们先还原两个实际工作场景

  • 当我们在使用v-for时,需要给单元加上key

  • ...
  • 用+new Date()生成的时间戳作为key,手动强制触发重新渲染

那么这背后的逻辑是什么,key的作用又是什么?

一句话来讲

key是给每一个vnode的唯一id,也是diff的一种优化策略,可以根据key,更准确, 更快的找到对应的vnode节点。

场景背后的逻辑

当我们在使用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数组插入数据

  

{{item}}

在不使用key的情况,vue会进行这样的操作:

分析下整体流程:

  • 比较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 内容非常简单,或者是刻意依赖默认行为以获取性能上的提升

三、原理分析

源码位置:core/vdom/patch.js

里判断是否为同一个key,首先判断的是key值是否相等如果没有设置key,那么key为undefined,这时候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]        }    }    ...}

读到这里,这篇"vue中设置key与不设置有什么区别"文章已经介绍完毕,想要掌握这篇文章的知识点还需要大家自己动手实践使用过才能领会,如果想了解更多相关内容的文章,欢迎关注行业资讯频道。

相同 数据 类型 节点 元素 更新 中设 不同 内容 文章 顺序 两个 例子 单元 场景 实例 情况 手动 效率 数据项 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 科技互联网项目 北京互联网络科技有限公司 壹账通互联网科技 奇士达互联网科技 时间互联网络科技 互联网金融 科技创新 深圳艾佳互联网科技 山东吉时兔互联网科技有限公司 青海省互联网新科技 湖南诚度互联网科技有限公司 河南猎农互联网科技有限公司 互联网媒体平台算高科技产业 畅思互联网科技 高科技互联网发展前景如何 互联网金融科技公司的优势 南通创西澳互联网科技有限公司 互联网公司高科技产品 互联网领先科技宣传片 互联网科技企业商标注意事项 保山浩联互联网科技有限公司 广东猪兼强互联网科技有限公司 金融科技与互联网金融 广州紫鲸互联网科技 中国最先进互联网科技公司 浙南科技城互联网大厦建设工程 洛阳共同富裕互联网科技有限公司 互联网金融科技名词解释 互联网科技企业商标注意事项 互联网科技博主张洲 承德科技产业互联网平台
0