vue和react项目中key的作用示例详解

 更新时间:2023年08月07日 10:59:41   作者:刘鹏瑜  
这篇文章主要为大家介绍了vue和react项目中key的作用示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

vue react对比新旧虚拟节点

vue和react都是采用diff算法来对比新旧虚拟节点,从而更新节点。

在交叉对比中,当新节点跟旧节点头尾交叉对比没有结果时,会根据新节点的key去对比旧节点数组中的key,从而找到相应的旧节点(这里对应的是一个key=>index的map映射)。

如果没有找到就认为是一个新增节点。而如果没有key,那么就会采用遍历查找的方式去找到对应的旧节点,一种一个map映射,另一种是遍历查找。相比而言,map映射速度更快。

vue部分源码如下

//vue项目 src/core/vdom/patch.js -448行
//oldCh是一个旧虚拟节点数组
if(isUndef(oldKeyToIdx)){
    oldKeyToIdx = createKeyToOldIdx(oldCh,oldStartIdx,oldEndIdx)
}
if(isDef(newStartVnode.key)){
    //map方式获取
    idxInOld = oldKeyToIdx[newStartVnode.key]
}else {
    //遍历方式获取
    idxInOld = findIdxInOld(newStartVnode,oldCh,oldStartIdx,oldEndIdx)
}

创建map函数

function createKeyToOldIdx(children,beginIdx,endIdx){
    let i,key
    const map = {}
    for(i = beginIdx;i<=endIdx;i++){
        key = children[i].key
        if(isDef(key)) map[key] = i    
    }
    return map
}

遍历寻找

//sameVnode 是对比新旧节点是否相同的函数
function findIdxInOld(node,oldCh,start,end){
    for(let i = start;i<end;i++){
        const c = oldCh[i]
        if(isDef(c) && sameVnode(node,c)) return i    
    }
}

上面的结论是基于没有key的情况diff速度会更快。确实,这种观点没有错。没有绑定key的情况下,并且在遍历模版简单的情况下,会导致虚拟新旧节点对比更快,节点也会复用。而这种复用是就地复用,一种鸭子辩型的复用。以下为简单的例子:

<div id="app">
    <div v-for="i in dataList">{{ i }}</div>
</div>
var vm = new Vue({
    el:'#app',
    data:{
        dataList:[1,2,3,4,5]    
    }
})

以上的例子,v-for的内容会生成以下的dom节点数组,我们给每一个节点标记一个身份id:

[
    '<div>1</div>',//id:A
    '<div>2</div>',//id:B
    '<div>3</div>',//id:C
    '<div>4</div>',//id:D
    '<div>5</div>',//id:E
]

改变dataList数据,进行数据位置替换,对比改变后的数据

vm.dataList = [4,1,3,5,2]//数据位置替换
//没有key的情况,节点位置不变,但是节点innerText内容更新了
[
    '<div>4</div>',//id:A
    '<div>1</div>',//id:B
    '<div>3</div>',//id:C
    '<div>5</div>',//id:D
    '<div>2</div>',//id:E
]
//有key的情况,dom节点位置进行了交换,但是内容没有更新
// <div v-for="i in dataList" :key='i'>{{ i }}</div>
[
    '<div>4</div>',//id:D
    '<div>1</div>',//id:A
    '<div>3</div>',//id:C
    '<div>5</div>',//id:E
    '<div>2</div>',//id:B
]

增删dataList列表项

vm.dataList = [3,4,5,6,7] //数据进行增删
// 1、没有key的情况,节点位置不变,内容也更新了
[
    '<div>3</div>',//id:A
    '<div>4</div>',//id:B
    '<div>5</div>',//id:C
    '<div>6</div>',//id:D
    '<div>7</div>',//id:E
]
// 2、有key的情况,节点删除了A B节点,新增了F G节点
// <div v-for="i in dataLIST" :key='i'>{{ i }}</div>
[
    '<div>3</div>',//id:C
    '<div>4</div>',//id:D
    '<div>5</div>',//id:E
    '<div>6</div>',//id:F
    '<div>7</div>',//id:G
]

从以上来看,不带有key,并且使用简单的模版,可以更有效的复用节点,diff速度也是不带key更加快速的,因为带有key在增删节点上有耗时。这就是vue文档所说的默认模式。但是这个并不是key作用,而是没有key的情况下可以对节点就地复用,提高性能。

这种模式会带来一些隐藏的副作用,比如可能不会产生过度效果,或者在某些节点有绑定数据(表单)状态,会出现状态错位。vue文档也说明了这个模式是高效的,但是只是适用于不依赖子组件状态或临时dom状态(例如:表单输入值)的列表渲染输出

但是key的作用是什么?

key是给每个vnode的唯一id,可以依靠key,更快的拿到oldVnode中对应的vnode节点。

1、更准确

因为带key就不是就地复用了,在sameNode函数a.key === b.key对比中可以避免就地服用的情况。所以会更加准确。

2、更快

利用key的唯一性生成map对象来获取对应节点,比遍历方式更快。

以上就是vue和react项目中key的作用示例详解的详细内容,更多关于vue react项目key作用的资料请关注脚本之家其它相关文章!

相关文章

  • 深入理解Vue的插件机制与install详细

    深入理解Vue的插件机制与install详细

    这篇文章主要介绍的是深入理解Vue的插件机制与install,文章主要是讲解install函数可以做些什么、install内部是怎么实现的、 Vuex,Vue-Router插件在install期间到底干了什么,需要的小伙伴可以参考一下
    2021-09-09
  • TypeScript踩坑之TS7053的问题及解决

    TypeScript踩坑之TS7053的问题及解决

    这篇文章主要介绍了TypeScript踩坑之TS7053的问题及解决,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-01-01
  • vue处理一千张图片进行分页加载思路详解

    vue处理一千张图片进行分页加载思路详解

    开发过程中,如果后端一次性返回你1000多条图片或数据,那我们前端应该怎么用什么思路去更好的渲染呢?这篇文章主要介绍了vue处理一千张图片进行分页加载,需要的朋友可以参考下
    2023-02-02
  • VUE + OPENLAYERS实现实时定位功能

    VUE + OPENLAYERS实现实时定位功能

    本系列文章介绍一个简单的实时定位示例,基于VUE + OPENLAYERS实现实时定位功能,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧
    2021-09-09
  • Vue项目中引入外部文件的方法(css、js、less)

    Vue项目中引入外部文件的方法(css、js、less)

    本篇文章主要介绍了Vue项目中引入外部文件的方法(css、js、less),非常具有实用价值,需要的朋友可以参考下
    2017-07-07
  • Vue3 列表界面数据展示详情

    Vue3 列表界面数据展示详情

    这篇文章主要介绍了Vue3 列表界面数据展示,文章主要详介绍的内容就是做的就是把打到页面的数据,带样式,也就是说好看点显示,需要的朋友可以参考一下
    2021-11-11
  • vue+iview+less 实现换肤功能

    vue+iview+less 实现换肤功能

    这篇文章主要介绍了vue+iview+less 实现换肤功能,项目搭建用的vue—cli,css框架选择的iview,具体操作流程大家跟随脚本之家小编一起看看吧
    2018-08-08
  • vue-cli3自动消除console.log()的调试信息方式

    vue-cli3自动消除console.log()的调试信息方式

    这篇文章主要介绍了vue-cli3自动消除console.log()的调试信息方式,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-10-10
  • vue-cli 3.0 引入mint-ui报错问题及解决

    vue-cli 3.0 引入mint-ui报错问题及解决

    这篇文章主要介绍了vue-cli 3.0 引入mint-ui报错问题及解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-05-05
  • vue数组双向绑定问题及$set用法说明

    vue数组双向绑定问题及$set用法说明

    这篇文章主要介绍了vue数组双向绑定问题及$set用法说明,具有很好的参考价值,希望大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-09-09

最新评论