热门标签 | HotTags
当前位置:  开发笔记 > 前端 > 正文

如何正确理解vue中的key详解

这篇文章主要给大家介绍了关于如何正确理解vue中key的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者使用vue具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧

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

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

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

Hello Vue.js !
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

  • ...

最常用的用法二:强制替换element或者component

  • 触发组件的lifecycle
  • 触发transition

 {{ text }}

text发生变化时,会被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,手动强制触发重新渲染

Hello Vue.js !
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渲染。

思考:

  • 为什么要叫propObj和propArr?
  • 带着父组件新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-...
https://vuejs.org/v2/guide/co...

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对的支持。


推荐阅读
  • 认识Vue关于Vue的描述有不少,不外乎都会拿来与Angular和React对比,同样头顶MVVM双向数据驱动设计模式光环的Angular自然被对比的最多,但到目前为止,Angul ... [详细]
  • 阿里Treebased Deep Match(TDM) 学习笔记及技术发展回顾
    本文介绍了阿里Treebased Deep Match(TDM)的学习笔记,同时回顾了工业界技术发展的几代演进。从基于统计的启发式规则方法到基于内积模型的向量检索方法,再到引入复杂深度学习模型的下一代匹配技术。文章详细解释了基于统计的启发式规则方法和基于内积模型的向量检索方法的原理和应用,并介绍了TDM的背景和优势。最后,文章提到了向量距离和基于向量聚类的索引结构对于加速匹配效率的作用。本文对于理解TDM的学习过程和了解匹配技术的发展具有重要意义。 ... [详细]
  • 本文详细解析了JavaScript中相称性推断的知识点,包括严厉相称和宽松相称的区别,以及范例转换的规则。针对不同类型的范例值,如差别范例值、统一类的原始范例值和统一类的复合范例值,都给出了具体的比较方法。对于宽松相称的情况,也解释了原始范例值和对象之间的比较规则。通过本文的学习,读者可以更好地理解JavaScript中相称性推断的概念和应用。 ... [详细]
  • 在Android开发中,使用Picasso库可以实现对网络图片的等比例缩放。本文介绍了使用Picasso库进行图片缩放的方法,并提供了具体的代码实现。通过获取图片的宽高,计算目标宽度和高度,并创建新图实现等比例缩放。 ... [详细]
  • 云原生边缘计算之KubeEdge简介及功能特点
    本文介绍了云原生边缘计算中的KubeEdge系统,该系统是一个开源系统,用于将容器化应用程序编排功能扩展到Edge的主机。它基于Kubernetes构建,并为网络应用程序提供基础架构支持。同时,KubeEdge具有离线模式、基于Kubernetes的节点、群集、应用程序和设备管理、资源优化等特点。此外,KubeEdge还支持跨平台工作,在私有、公共和混合云中都可以运行。同时,KubeEdge还提供数据管理和数据分析管道引擎的支持。最后,本文还介绍了KubeEdge系统生成证书的方法。 ... [详细]
  • 生成对抗式网络GAN及其衍生CGAN、DCGAN、WGAN、LSGAN、BEGAN介绍
    一、GAN原理介绍学习GAN的第一篇论文当然由是IanGoodfellow于2014年发表的GenerativeAdversarialNetworks(论文下载链接arxiv:[h ... [详细]
  • JavaScript设计模式之策略模式(Strategy Pattern)的优势及应用
    本文介绍了JavaScript设计模式之策略模式(Strategy Pattern)的定义和优势,策略模式可以避免代码中的多重判断条件,体现了开放-封闭原则。同时,策略模式的应用可以使系统的算法重复利用,避免复制粘贴。然而,策略模式也会增加策略类的数量,违反最少知识原则,需要了解各种策略类才能更好地应用于业务中。本文还以员工年终奖的计算为例,说明了策略模式的应用场景和实现方式。 ... [详细]
  • 本文介绍了PhysioNet网站提供的生理信号处理工具箱WFDB Toolbox for Matlab的安装和使用方法。通过下载并添加到Matlab路径中或直接在Matlab中输入相关内容,即可完成安装。该工具箱提供了一系列函数,可以方便地处理生理信号数据。详细的安装和使用方法可以参考本文内容。 ... [详细]
  • 无损压缩算法专题——LZSS算法实现
    本文介绍了基于无损压缩算法专题的LZSS算法实现。通过Python和C两种语言的代码实现了对任意文件的压缩和解压功能。详细介绍了LZSS算法的原理和实现过程,以及代码中的注释。 ... [详细]
  • 本文介绍了数模国赛的报名参加方法,包括学校报名和自己报名的途径。同时给出了建模竞赛的建议,重在历练的同时掌握方法以及弥补自己的短板。此外,还分享了论文的结构和模型求解部分的注意事项,包括数学命题的表述规范和计算方法的原理等。 ... [详细]
  • 媒介本文的前身是源自github上的项目awesome-github-vue,但由于该项目上次更新时候为2017年6月12日,许多内容早已逾期或是许多近期优异组件未被收录,所以小肆 ... [详细]
  • 本文涉及源码版本为2.6.9准备工作down一份Vue源码,从package.json入手,找我们需要的代码1、package.json中的scripts,build:nodesc ... [详细]
  • sklearn数据集库中的常用数据集类型介绍
    本文介绍了sklearn数据集库中常用的数据集类型,包括玩具数据集和样本生成器。其中详细介绍了波士顿房价数据集,包含了波士顿506处房屋的13种不同特征以及房屋价格,适用于回归任务。 ... [详细]
  • 计算机存储系统的层次结构及其优势
    本文介绍了计算机存储系统的层次结构,包括高速缓存、主存储器和辅助存储器三个层次。通过分层存储数据可以提高程序的执行效率。计算机存储系统的层次结构将各种不同存储容量、存取速度和价格的存储器有机组合成整体,形成可寻址存储空间比主存储器空间大得多的存储整体。由于辅助存储器容量大、价格低,使得整体存储系统的平均价格降低。同时,高速缓存的存取速度可以和CPU的工作速度相匹配,进一步提高程序执行效率。 ... [详细]
  • 《数据结构》学习笔记3——串匹配算法性能评估
    本文主要讨论串匹配算法的性能评估,包括模式匹配、字符种类数量、算法复杂度等内容。通过借助C++中的头文件和库,可以实现对串的匹配操作。其中蛮力算法的复杂度为O(m*n),通过随机取出长度为m的子串作为模式P,在文本T中进行匹配,统计平均复杂度。对于成功和失败的匹配分别进行测试,分析其平均复杂度。详情请参考相关学习资源。 ... [详细]
author-avatar
溟尛樂_840
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有