如何理解vue中的key?

从Vue的DOM构建机制中理解key 最近在学vue,看完vue的基础部分后大部分的知识都很容易理解,唯独频频提到的key让我疑惑了很久~官方文档上对key的第一次描述是:如果只是单纯的看文档,理解的可能不是太清楚,所以我专门写了上面这个demo来验证文档所说的:先看效果:    普通的for循环(没加key)         加了key值得for循环可以发现在普通的v-for循环中,在我点击删除后,第一个被选中的input并没有一并... 阅读详情

在这里插入图片描述

就目前所了解的情况,key的作用有以下这些。

  • v-for遍历时,用id,uuid之类作为key,唯一标识节点加速虚拟DOM渲染
  • 响应式系统没有监听到的数据,用+new Date()生成的时间戳作为key,手动强制触发重新渲染

场景一大同小异司空见惯,场景二是下面这样的:

<div :key="rerender">
    <span>Hello Vue.js !</span>
    <complexComponent :propObj="propObj" :propArr="propArr" ></complexComponent>
</div>

refresh(){
    this.rerender = + new Date();
}

那么vue中key的相关知识点到底是怎样的呢?

  • 官方API知识点
  • 上面2个使用场景背后的原理是什么?
  • 除key外,还有其它强制更新DOM的方法吗?
  • 参考资料

官方API知识点

  • 在Vue.js中,key是6个特殊属性key, ref, is, slot, slot-scope, scope其中之一。
  • key的值可以是number,也可以是string。
  • key主要作用于Vue的virtual DOM算法,在diff new nodes list和old nodes list时,作为识别VNode的一个线索。
  • 如果不用key,Vue会用一种算法:最小化element的移动,并且会尝试尽最大程度在同适当的地方对相同类型的element,做patch或者reuse。
  • 如果使用了key,Vue会根据keys的顺序记录element,曾经拥有了key的element如果不再出现的话,会被直接remove或者destoryed。
  • 拥有同一个parent的children必须有unique keys。重复的key的导致render error。
最常用的用法一:v-for
<ul>
    <li v-for="item in items" :key="item.id">...</li>
</ul>
最常用的用法二:强制替换element或者component
  • 触发组件的lifecycle
  • 触发transition
<transition>
  <span :key="text">{{ text }}</span>
</transition>

text发生变化时,<span>会被replaced,而不会patched,因此transition会被触发。
我的理解:
text变化时,span的key发生了变化,也就是说曾经拥有了旧key的span不再出现了,当拥有新值的text作为key时,拥有了新key的span出现了,那么旧key span会被移除,旧transition也会移除,新key span触发渲染,新transition触发。

上面2个使用场景背后的原理是什么?

结合官方API的知识点,现在再来回顾文章开头提出的场景。

场景一:v-for遍历时,用id,uuid之类作为key,唯一标识节点加速虚拟DOM渲染

答案:

  • 如果不用key,Vue会用一种算法:最小化element的移动,并且会尝试尽最大程度在同适当的地方对相同类型的element,做patch或者reuse。
  • 如果使用了key,Vue会根据keys的顺序记录element,曾经拥有了key的element如果不再出现的话,会被直接remove或者destoryed。
场景二:响应式系统没有监听到的数据,用+new Date()生成的时间戳作为key,手动强制触发重新渲染
<div :key="rerender">
    <span>Hello Vue.js !</span>
    <complexComponent :propObj="propObj" :propArr="propArr" ></complexComponent>
</div>

refresh(){
    this.rerender = + new Date();
}

答案:

  • 如果使用了key,Vue会根据keys的顺序记录element,曾经拥有了key的element如果不再出现的话,会被直接remove或者destoryed。
  • refresh方法调用后,包含了span和complexComponent的div的key发生了变化,也就是说曾经拥有了旧key的div不再出现了,当拥有新值的rerender作为key时,拥有了新key的div出现了,那么旧key div会被移除,旧span和complexComponent也会移除,新key div触发渲染,新span,带着父组件新propObj和propArr的新complexComponent渲染。

思考:

  1. 为什么要叫propObj和propArr?
  2. 带着父组件新propObj和propArr的新complexComponent渲染。 为什么要加粗?

由于Vue.js的obj和arr存在无法检测到数据变化的情况,obj是属性的新增和删除(原因是新增和删除都没有触发setter,watcher未告诉外界更新),arr则是数组内元素重新赋值或者修改length属性(原因是没有使用改变数组本身的方法,没有触发数组原型链拦截器,watcher未告诉外界更新)。
所以!通过赋予新key的方式,移除旧key div,渲染新key div,propObj和propArr在complexComponent组件内会重新触发一次生命周期,做一次重新渲染。**此时父组件的propObj和propArr js变量其实已经获取到新值了,只是没有触发DOM也好,VNode也好的重新渲染。**需要通过刷新key去force update,说到forceUpdate,可以通过$forceUpdate()去手动强制更新DOM。

除key外,还有其它强制更新DOM的方法吗?

场景:父组件修改传递给子组件的数据,数组数据的更新没有按照this.$set去更新。该怎么办?

this.productImages.forEach((product) => {
  if (product.productId in this.productsState) {
    product.status = this.productsState[product.productId];
  }
});

不使用this.$set去赋值数据的不能rerender的原因是什么?
在Vue.js中,对Array的变化侦测是通过拦截原型的方式实现的。也就通过对push,pop,shift,unshift,splice,sort,reverse,fill,copyWithin去改变数组自身内容的方法做拦截,从而响应。而product.status = this.productsState[product.productId];没有触发任何改变数组自身的被监听的方法,因此不会rerender。

  • 刷新组件的key
  • $forceUpdate方法
刷新组件的key
1.这个key加在什么地方比较好?

加在this.productImages的父元素上就好。
若不涉及数据传递,也可以直接加在需要更新的element上。

2.用什么做key值?

现在是粗暴的+new Date()时间戳做key值的。
也可以用双向绑定的值作为key值,保证新旧key值不同就行。

3.key的原理是什么?

vue.js的虚拟DOM算法,在更新vNode时,需要从旧vNode列表中查找与新vNode节点相同的vNode进行更新,如果这个过程设置了属性key,过程就会快很多。
其他具体见上文。

$forceUpdate方法

只能在父组件调用这个方法,手动通知vue实例重新渲染。

// $forceUpdate源码
Vue.prototype.$forceUpdate = function () {
  const vm: Component = this
  if (vm._watcher) {
    vm._watcher.update()
  }
}
// update源码
/**
 * Subscriber interface.
 * Will be called when a dependency changes.
 */
update () {
  /* istanbul ignore else */
  if (this.lazy) {
    this.dirty = true
  } else if (this.sync) {
    this.run()
  } else {
    queueWatcher(this)
  }
}
1.$forceUpdate可以更新的原理分析

product.status = this.productsState[product.productId];以后,其实此时dep已经发生变化了,但是Vue.js数组响应式的实现由于是拦截原型链方法的方式,没有检测到这个变化,所以不会自动rerender,没有触发update。因此我们通过$forceUpdate的方式,调用包含dep的watcher上的update方法,从而做到rerender。

2.可以在子组件监听事件,父组件发送事件然后只刷新子组件吗?

不可以。
因为dep是父组件的watcher和dep,并不是子组件,是父组件的this.productImages没有被检测到并实时更新,并不是子组件的问题。

参考资料

https://vuejs.org/v2/api/#key
https://vuejs.org/v2/api/#vm-forceUpdate
https://vuejs.org/v2/guide/components-edge-cases.html#Forcing-an-Update

原文链接:https://github.com/FrankKai/FrankKai.github.io/issues/167

期待和大家交流,共同进步,欢迎大家加入我创建的与前端开发密切相关的技术讨论小组:

努力成为优秀前端工程师!

你知道vue中key的原理吗?说说你对它的理解 如果数据项的顺序被改变,Vue 将不会移动 DOM 元素来匹配数据项的顺序, 而是简单复用此处每个元素,并且确保它在特定索引下显示已被渲染过的每个元素。如果不用key,Vue会采用就地复地原则:最小化element的移动,并且会尝试尽最大程度在同适当的地方对相同类型的element,做patch或者reuse。key是给每一个vnode的唯一id,也是diff的一种优化策略,可以根据key,更准确, 更快的找到对应的vnode节点。,然后将比对出的结果用来更新真实的。那么这背后的逻辑是什么, 阅读详情

相关推荐

VS2010“未能正确加载包”问题解决方法小汇

本文按照由简至繁的顺序详述了借助网络获知的四种解法,主要面向重装 VS2010 后遭遇题述问题的网友,相关包尤指 VSTS、RadLangSvc、Language、Bootstrap 及 MicrosoftDataEntityDesign。

虚有其表的博客 1万+

js修改对象数组的key值

实例:将dataOld这个对象数组的对象中的属性key变成dataNew中的形式; 方法一:使用map循环,在map循环内创建一个新对象,将item要改变的key赋给新创建的对象里面新key值,然后push给一个新创建的数组dataNew即可; 方法二:使用map循环 + replace替换,通过循环然后将子类JSON.stringify后采用replace来改变属性key; 方法三:使用forEach循环 + for循环,通过Object.keys()来改变属性key; 结果:...

lemon今天学习了吗?的博客 2万+

环境科研人必备:手把手教你用EPISuite 4.1批量预测化合物毒性(附ECOSAR实战)

本文详细介绍了EPISuite 4.1在环境毒理学研究中的应用,重点解析了ECOSAR模块的化合物毒性预测技术。通过批量处理实战和科研案例,帮助环境科研人员快速评估化学物质对水生生态系统的风险,提升工作效率。文章还涵盖了EPISuite核心模块的功能分类及ECOSAR模型的技术原理与算法特点。

weixin_28738165的博客 540

我常用的几个 VueUse 最佳组合,推荐给你们!

当一个对象的属性键是上述类型的组合时,该对象的非负整数键(可枚举和不可枚举)首先按升序添加到数组中,然后按插入顺序添加字符串键。最后,Symbol键按插入顺序加入。100100,00,a'a','a',};',key);}但是,如果你强烈依赖插入顺序,那么Map可以保证这一点。编辑中可能存在的bug没法实时知道,事后为了解决这些bug,花了大量的时间进行log调试,这边顺便给大家推荐一个好用的BUG监控工具Fundebug。作者islizeqiang译者小智来源。...

粉丝们务必加入微信粉丝群 2570

【深度学习-番外1】Win10系统搭建VSCode+Anaconda+Pytorch+CUDA深度学习环境和框架全过程

本文将介绍在Windows 10系统下搭建深度学习环境的完整过程,包括安装Anaconda、CUDA、NVIDIA显卡驱动以及Pytorch框架。后续本专栏的Python语言下的深度学习环境都以本篇搭建的为准。

fengzhuqiaoqiu的博客 4000

Ubuntu 24.04 高效部署Slurm集群:从零到生产环境实战

本文提供了一份在Ubuntu 24.04 LTS系统上从零开始部署生产级Slurm高性能计算集群的完整实战指南。内容涵盖网络配置、Munge安全认证、Slurm核心组件安装与配置,并深入讲解了cgroups资源隔离、NFS共享存储、配置无感知模式等生产环境优化技巧,最后通过实例演示如何提交与管理Slurm作业,帮助用户构建高效、稳定的计算平台。

weixin_29213655的博客 564

日期格式之——new Date()的用法

获取时间: 1 varmyDate =newDate();//获取系统当前时间 获取特定格式的时间: 1 myDate.getYear(); //获取当前年份(2位) 2 myDate.getFullYear(); //获取完整的年份(4位,1970-????) 3 myDate.getMont...

weixin_30357231的博客 1749

视觉惯性SLAM系列——ORB-SLAM3的整体介绍及各个线程的功能(五)

跟踪线程(Tracking Thread)作用:负责处理每一帧图像,进行相机位姿的估计和定位。它首先执行与前一帧图像的特征匹配,然后通过仅运动(motion-only)BA(Bundle Adjustment)优化位姿。如果跟踪失败,它会尝试在所有地图中进行重定位。此外,跟踪线程还负责决定何时插入新的关键帧,以及何时将关键帧从局部地图中移除。详细介绍见局部建图线程(Local Mapping Thread)作用:管理局部地图,向活跃地图添加关键帧和点,移除多余的关键帧和点。

曾经也曾立志 1004

Vue 刷新路由

给路由加个Key,点刷新改变Key即可 <router-view :key="rootkey" /> data() { return { //路由的key rootkey: new Date().getTime(), }; }, //刷新 onReload(icon) { if (icon == "redo") { this.rootkey = new Date().getTime(); }

℡メ㏑╭ァ小凯 1482

Python爬虫实战 | 拼多多商品评论采集与深度分析

本文从 API 调用、网页渲染到情感分析与关键词提取,全流程剖析了“拼多多商品评论采集与分析”项目。Scrapy + API 可快速抓取评论;Playwright 可突破 API 限制,抓取完整页面内容;数据清洗 + 分析揭示用户真实反馈;可持续部署、扩展至更多商品 & 时间段;

2201_76125261的博客 1696

ANSYS——模态分析的理论基础

ANSYS模态分析理论基础

python_AI_fans的博客 9078

Vue中使用new Date().getTime()作为组件遍历时的key值会导致组件不断销毁和创建的问题

在项目中遇到的一个问题,在子组件中监听父组件给其传递的一个值,但发现监听回调不生效,经反复调试发现,子组件多次触发了created和destroyed生命周期钩子,也就是说子组件被多次的创建和销毁。当key的值发生变化时,Vue会认为这是一个新的组件,因此会销毁旧的组件实例并创建一个新的组件实例,这就导致了组件不断销毁和创建的循环。要解决这个问题,就需要使用一个稳定的、唯一的值作为:key的值,而不是使用每次渲染时生成的随机时间戳。查啊查原因,说是每次渲染时,

qq_45560350的博客 4020

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

关于vue列表渲染的key理解

关于vue v-for 里的key,文章都一大把了,但是,并不是每个人都说的准确或说到位了,这里谈谈个人理解。 key的作用,就是为了帮助比较前后vnode是不是相同vnode。如果匹配到了相同节点,那就可以直接复用。 但是用什么作为key呢,我们讨论一下以下几种情况 不加key 用随机数 用数组索引 用数组元素唯一属性,如id 讨论前我们先看一下vue对于是否为sameVnode的判断逻辑,这里我们关注a.key===b.key就可以了,至于更详细的diff过程可以看看这篇详解vue d.

illusion_melody的博客 902

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

vue中key的理解

如果不用key,Vue会采用就地复地原则:最小化element的移动,并且会尝试尽最大程度在同适当的地方对相同类型的element,做patch或者reuse。如果使用了key,Vue会根据keys的顺序记录element,曾经拥有了key的element如果不再出现的话,会被直接remove或者destoryed。当拥有新值的rerender作为key时,拥有了新key的Comp出现了,那么旧key Comp会被移除,新key Comp触发渲染。渲染错误:如果列表项的顺序发生变化,Vue。

m0_62201781的博客 421

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

vue中对:key的理解

<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> </head> <body> <div id="app"> <span v-if="isUser"> ...

codingWeb的博客 603

如何理解vue的key属性

如果没有这个属性的时候vue应用 in-place patch(就地复用)策略。列表里的顺序发生改变的时候比如shuffle(列表打乱)的时候,vue为了提升性能,不会移动dom元素,只是更新相应元素的内容节点。 就地复用的弊端 这个默认的模式是高效的,但是只适用于不依赖子组件状态或临时 DOM 状态 (例如:表单输入值) 的列表渲染输出。 如上引用自官网,这个模式就是上面的“就地复用”策略。...

weixin_34378767的博客 388

VUE中key的理解

vue、key

weixin_50996110的博客 1080

vue 用key拿对象value_如何正确理解vue中的key详解

就目前所了解的情况,key的作用有以下这些。v-for遍历时,用id,uuid之类作为key,唯一标识节点加速虚拟DOM渲染响应式系统没有监听到的数据,用+new Date()生成的时间戳作为key,手动强制触发重新渲染场景一大同小异司空见惯,场景二是下面这样的:Hello Vue.js !refresh(){this.rerender = + new Date();}那么vue中key的相关知识...

weixin_39596739的博客 1592

如何理解vue中的key

如何理解vue中的key? 就目前所了解的情况,key的作用有以下这些。 v-for遍历时,用id,uuid之类作为key,唯一标识节点加速虚拟DOM渲染 响应式系统没有监听到的数据,用+new Date()生成的时间戳作为key,手动强制触发重新渲染 场景一大同小异司空见惯,场景二是下面这样的: <div :key="rerender"> <span>Hello Vue.js !</span> <complexComponent :propOb

song854601134的博客 506

理解Vue中 key 的作用

关键词:diff算法,Virtual DOM,快速 key的特殊属性主要用在 Vue 的虚拟 DOM 算法,在新旧 nodes 对比时辨识 VNodes。 如果不使用 key,Vue 会使用一种最大限度减少动态元素并且尽可能的尝试就地修改/复用相同类型元素的算法。 而使用 key 时,它会基于 key 的变化重新排列元素顺序,并且会移除 key 不存在的元素。 有相同父元素的子元素必须有...

weixin_39307273的博客 3451

新手对vue中特殊的标签属性ref和key的理解

vue中特殊的标签属性ref和key的详解

背心的博客 1398

Vue中关于v-for循环时添加key属性问题与理解

Vue中关于v-for循环时添加key属性问题与理解

qq_52753587的博客 1910
上一篇: PostCSS真的太好用了!
下一篇: 如何理解mqtt用到的101交换协议?
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

趁你还年轻233

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值