关键词:
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对象来获取对应节点,比遍历方式更快。
diffing算法以及key值的作用(代码片段)
在react/vue中key有什么作用?内部原理是什么?一.虚拟dom中key的作用简单的来说key就是虚拟dom对象中的标识,在更新显示时key有很重要的作用原理:当状态中的数据发生改变的时候,react会根据【新数据】生成... 查看详情
你知道vue中key的作用和工作原理吗?说说你对它的理解。(代码片段)
你知道vue中key的作用和工作原理吗?说说你对它的理解。原码中找答案:src\\corelvdom\\patch.js-updateChildren()测试代码如下<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><metahttp-equiv="X-UA-Compatible"c 查看详情
vue条件渲染,列表渲染,key的作用和原理,列表过滤,列表排序,vue监测数据原理和注意事项(代码片段)
文章目录1.条件渲染2.列表渲染3.key的作用和原理3.1index作为key的效果和问题3.1id作为key的效果(最佳)3.3两个总结4.列表过滤4.1通过watch,filter和indexOf()来实现4.2通过使用computed,filter和indexOf()来实现5.列表排序6.深度了解Vue如... 查看详情
react和vue区别以及为啥会说react适合大型项目
参考技术A都说react适合做大型项目,但是什么是大型项目呢。首先在上方已经说过,选用vue或者react作为大型项目的框架主要还是在于人,在于开发团队的统合程度那为什么还要说react更适合大型项目呢,支点是什么呢?2.react社... 查看详情
高级前端面试题目大全(代码片段)
第1题:(滴滴、饿了么)写React/Vue项目时为什么要在列表组件中写key,其作用是什么?1.更准确因为带key就不是就地复用了,在sameNode函数a.key===b.key对比中可以避免就地复用的情况。所以会更加准确。2.更快利用key的唯一性... 查看详情
vue学习总结笔记(代码片段)
...e的class绑定样式改变数值2.条件渲染3.Vue的列表渲染4.key的作用和原理4.1index作为key的效果和问题4.2id作为key的效果(最佳)3.3面试题:react,vue中的key有什么作用?5.列表过滤5.1#region和#endregion5.2使用watch和vue中的filter方法... 查看详情
vue中使用v-for渲染数据为何要添加key属性?(原理及作用)
参考技术A在Vue中使用v-for进行列表渲染的时候,它会默认使用“就地更新”的策略。当Vue在进行列表渲染的时候,Vue会直接对已有的标签就地更新,并不会将所有的标签全部重新删除和重建,只会重新渲染数据,然后再创建新的... 查看详情
vue中key的作用
key是为每个vnode指定唯一的id,在同级vnode的Diff过程中,可以根据key快速的进行对比,来判断是否为相同节点,利用key的唯一性生成map对象来获取对应节点,比遍历方式更快,指定key后,可以保证渲染的准确性(尽可能的复用DOM元素... 查看详情
路由在 webpack + react 项目中不起作用
】路由在webpack+react项目中不起作用【英文标题】:Routingnotworkinginawebpack+reactproject【发布时间】:2021-11-2421:58:03【问题描述】:我正在使用webpack+React+react-router+typescript构建一个应用程序,但我被路由卡住了,我有两个路由,默认... 查看详情
vue中key值的作用(代码片段)
Vue中key值的作用首先v-for在列表渲染时,我们可以用v-for基于一个数组来渲染一个列表。v-for指令需要使用iteminarr形式的特殊语法来进行渲染列表,arr是源数据,<ulid="example-1"><liv-for="iteminarr":key... 查看详情
渲染一颗树(分别使用vue和react创建)
...传树形结构数组。vue通过组件递归将数据渲染出一颗树,react则通过函数递归,数据结构:treeData:[label:‘1‘,key:‘1‘,children:[label:‘1-1‘,key:‘11‘,label:‘1-2‘,key:‘12‘],label:‘2‘,key:‘ 查看详情
react的数据渲染循环key的作用
...技术A1.key是虚拟dom对象的标识,在更新显示时起到重要的作用2.当状态中的数据发生变化的时候,react会根据【新数据】生成【新的虚拟DOM】,随后React进行【新虚拟DOM】与【旧虚拟DOM】的diff比较,比较规则见33.当旧虚拟DOM找到... 查看详情
在react或vue中,for循环用index作为key值是好还是坏呢?
React与vue的基本实现原理是通过对比两次虚拟dom的不同然后直接操作不同的dom 当以数组的下标index作为key值时 其中一个元素发生了变化就有可能导致所有元素的key值发生改变 diff算法是比较同级之间的不同 以k... 查看详情
关于vue列表渲染key绑定index的性能问题(代码片段)
...值(index)性能的问题:React官方文档原文:“如果列表项目的顺序可能会变化,我们不建议使用索引来用作key值,因为这样做会导致性能变差,还可能引起组件状态的问题”。查阅网上的博客,确实有对Vue列表渲染key绑定索引... 查看详情
react的diffing算法(面试题)(代码片段)
...来的那个真实DOM。经典面试题:react/vue中的key有什么作用?(key的内部原理是什么?)为什么遍历列表时,key最好不要用index?虚拟DOM中key的作用简单说,key是虚拟DOM对象的标识,在更新显示时key起着极其重要的作用... 查看详情
支持复杂场景的vue和react集成引用的js插件
...中使用vue的组件在react组件中,向vue组件传递具名插槽和作用域插槽,以及绑定自定义事件,以及v-model应用react本身并不支持v-model,所以需要通过model的value和setter也不需要变化在react组件动态引用vue组件,类似vue的<component/>... 查看详情
虚拟dom(vuereact)中key的作用(代码片段)
虚拟DOM中key的作用:(1)简单的说:key是虚拟DOM对象的标识,在更新显示时key起着极其重要的作用。(2)详细的说:当状态中的数据发生变化时,react会根据【新数据】生成【新的虚拟DON】,随后React进行【新... 查看详情
vue中main.js的作用
参考技术Amain.js是项目的入口文件,项目中所有的页面都会加载main.js,所以main.js,主要有三个作用:1.实例化Vue。2.放置项目中经常会用到的插件和CSS样式。例如:网络请求插件:axios和vue-resource、图片懒加载插件:vue-lazyload3.存储全... 查看详情