vue中key,keep-alive理解。

vue中key,keep-alive理解。,第1张

避免dom元素重复渲染 我们一般设置一个唯一标识作为key值,id或者index下标。

keep-alive是vue内置的⼀个组件,这个组件的作⽤就是能够缓存不活动的组件,⼀般情况下,组件进⾏切换的时候,默认会进⾏销毁,如果有需求,某个组件切换后不进⾏销毁,⽽是保存之前的状态,⽐如说刚刚填好的表单数据。那么就可以利⽤keep-alive来实现。

在搭建 vue 项⽬时,有某些路由组件没必要多次渲染,所以需要将组件在内存中进⾏‘持久化’,此时在router-view上使⽤keep-alive。 keep-alive可以使被包含的路由组件状态维持不变,即便是组件切换了,其内的状态依旧维持在内存之中。在下⼀次显示时,也不会重新渲染。

include - 字符串或正则表达式。只有名称匹配的组件会被缓存。 exclude - 字符串或正则表达式。任何名称匹配的组件都不会被缓存。 max-数字最多可以缓存多少组件。

1、虚拟DOM中key的作用:

key是虚拟DOM中对象的标识,当数据发生变化时,Vue会根据新数据生成新的虚拟DOM,随后Vue进行新虚拟DOM与旧虚拟DOM的差异比较,比较规则如下:

2、对比规则:

1)旧虚拟DOM中找到了与新虚拟DOM相同的key:

        a若虚拟DOM中内容没变, 直接使用之前的真实DOM

        b若虚拟DOM中内容变了, 则生成新的真实DOM,随后替换掉页面中之前的真实DOM

2)旧虚拟DOM中未找到与新虚拟DOM相同的key:创建新的真实DOM,随后渲染到到页面

3、用index作为key可能会引发的问题:

a若对数据进行逆序添加、逆序删除等破坏顺序 *** 作:会产生没有必要的真实DOM更新 ==> 界面效果没问题, 但效率低

b若结构中还包含输入类的DOM:会产生错误DOM更新 ==> 界面有问题

4、开发中如何选择key

a最好使用每条数据的唯一标识作为key,比如id、手机号、身份z号、学号等唯一值

b如果不存在对数据的逆序添加、逆序删除等破坏顺序的 *** 作,仅用于渲染列表,使用index作为key是没有问题的

今天思考一个问题,在子组件中,key值的作用是什么?

如果一个组件, <A key="1" /> 改边key的值, <A key="2" /> ,发生什么?

实践出真理,测试一下:

首先,创建一个子组件:

一个非常简单的组件,在各个生命周期上,绑定事件:

接下来,通过父组件修改子组件的key值:

看看运行起来是什么情况:

点击按钮之后,发现:

通过patch函数,可以看到,首先需要对比两个节点是否是相同节点,(相同的组件,难道不是相同节点吗?)

进入sameVnode函数看看:

恍然大悟,原来在diff的时候,不仅是对比元素的标签名,还会去对比元素的key值,key值一旦改变,就算子节点的内容一模一样,也是会进入到patch函数的else中,那么这个时候,执行的 *** 作就是新建新组件=>删除旧组件=>添加新组件。

因此,可以看到生命周期是新组件的生命周期先执行,再进行旧组件的销毁,接着挂载新组件。

emmmm

那么再思考深一层的问题,如果是列表渲染的时候,key值设为id,和index会有什么区别呢??

同样的做一个测验:创建一个子组件,子组件里包含一个孙子组件

接着,在原先的<key-com/>组件里:

创建2个Child组件,它们的区别就是一个使用index作为key,一个使用id作为key:

运行之后就可以看到它们的区别:

点击删除之后数组是:

先对比id从[1,2,3]变成了[1,3],即第二项被删除了。

因此: key值为何不能用index作为值?

如果你用index作为key值的时候,在删除第二项时,index就从1,2,3变成1,2;而不是1,3。

VUE是通过比对组件自身新旧vdom进行更新的。key的作用是辅助判断新旧vdom节点在逻辑上是不是同一个对象。

因此可以确定,渲染列表时,key值需要一个唯一确定的id来赋值。

因为不理解 :key(v-bind:key),网上查了一些的资料,这篇写得非常不错,很简洁清楚。

其实不只是vue,react中在执行列表渲染时也会要求给每个组件添加上key这个属性。

要解释key的作用,不得不先介绍一下虚拟DOM的Diff算法了。

我们知道,vue和react都实现了一套虚拟DOM,使我们可以不直接 *** 作DOM元素,只 *** 作数据便可以重新渲染页面。而隐藏在背后的原理便是其高效的Diff算法。

1 两个相同的组件产生类似的DOM结构,不同的组件产生不同的DOM结构。

2 同一层级的一组节点,他们可以通过唯一的id进行区分。

基于以上这两点假设,使得虚拟DOM的Diff算法的复杂度从 O(n^3) 降到了 O(n)

这里我们借用 React’s diff algorithm 中的一张图来简单说明一下:

如果节点类型不同,直接干掉前面的节点,再创建并插入新的节点,不会再比较这个节点以后的子节点了。

如果节点类型相同,则会重新设置该节点的属性,从而实现节点的更新。

比如一下这个情况:

我们希望可以在B和C之间加一个F,Diff算法默认执行起来是这样的:

即把C更新成F,D更新成C,E更新成D,最后再插入E,是不是很没有效率?

所以我们需要使用key来给每个节点做一个唯一标识,Diff算法就可以正确的识别此节点,找到正确的位置区插入新的节点。

否则vue只会替换其内部属性而不会触发过渡效果。

步骤:

最好使用每条数据的唯一标识作为key, 比如id、手机号、身份z号、学号等唯一值。

如果不存在对数据的逆序添加、逆序删除等破坏顺序 *** 作,仅用于渲染列表用于展示,

使用index作为key是没有问题的。

首先 什么是虚拟节点?

        一般来说HTML的元素解析成DOM树后,真实挂载的元素就是Node。而VNode(虚拟节点)(本质是一个JS对象)是Vue解析template里面的元素生成的,而这些VNode组成就会形成一个VNodeTree(虚拟DOM),而虚拟DOM再经过一些 *** 作才会变成真实的DOM(不一定是一一对应的)。所以VNode可以做多平台的渲染。

那么 如果使用v-for列表渲染一个数组,那么有个添加 *** 作,在数组中间插入一个元素,那么插入渲染怎么才可以性能更好?

没有key就会调用patchUnKeyedChildren方法

        Vue源码会有c1保存着旧的VNode,c2保存着新的VNode,Vue内部就会先获取旧的和新的VNode数组(列表)的长度,再Mathmin(c1length,c2length)获取新旧数组中长度最短的值,然后遍历短的VNode列表(为什么会判短的,因为要避免越界的情况),分别获取c2和c1里面的一个值,下一步就进行新旧VNode的patch(更新),相同的就不更新,不同的就更新(如果类型相同,但是里面的内容不同,就只更新里面的内容就可以),直到遍历完。因为用的是短的遍历,如果旧的VNode数大于新的VNode数,多出来的旧VNode就会被卸载(unmountChildren)掉,如果旧的VNode数小于新的VNode数,就会创建新的VNode, 然后挂载(mountChildren)到新的VNode列表里,形成新的虚拟DOM后,最后渲染到真实的DOM(而这种处理方法的性能低)。

本萌新理解:就是相同的VNode尽可能的复用,不同就复用VNode节点,再修改内容。

key属性主要用在Vue的虚拟DOM算法,在新旧nodes对比时辨识VNodes。

         如果使用key,就会使用patchUnkeyedChildren方法,这时vue就采用了diff算法。 当执行元素插进去数组中,vue会新生成一个新的VNodes并和原本的VNodes进行比较。(开发中,一般绑定key就是其代表内容的一致性)

        Vue考虑到中间插入删除 *** 作,就会先进行前面和后面的VNode比较,然后在中间就插入新的VNode,也考虑到随便在中间删了一个VNode。Vue内部用一个while循环(因为Vue不知道要在哪儿结束,VNode数量的不确定性)

        第一步,从头部开始遍历,找到新旧VNode数组(列表)里的第一个VNode,然后判断它们的type和key是否一样,如果VNode相同,就会进行patch,然后继续循环遍历,直到查找到不是新旧VNode就不同,才会跳出循环。

        第二步,开始从尾部开始进行遍历,判断它们的VNode是否相同,相同就patch,不同就直接跳出循环。

        第三步,如果旧VNode数组遍历完,新VNode数组还有VNode(新的VNode),就会找到该VNode的位置,然后patch一个null(表示一次挂载 *** 作),新VNode列表就会在该位置新增一个VNode。

        第四步,如果新VNode数组遍历完,旧VNode数组里还有VNode,就找到对应位置的Vnode,直接卸载掉。

        第五步,如果前后都比较完后,新旧VNode数组中间部分的VNode数相等(或不等)并且无序,Vue会新建一个数组arr,会尽可能在旧VNode数组里找到对应新VNode数组的VNode,其实就是根据key建立索引找到它们相同的VNode,然后把旧VNode数组里含有的这个VNode放到arr里,直到相同的旧Vnode都patch完放到arr后,而这时如果旧VNode数组里还有多出来的VNode就会被卸载掉,而新VNode数组里还有多出来的VNode就会被放入arr里,最后再把arr插入到新的VNode中间。

<!DOCTYPE html>

<html>

<head>

<meta charset="utf-8">

<title>test</title>

<script src=">

以上就是关于vue中key,keep-alive理解。全部的内容,包括:vue中key,keep-alive理解。、react、vue中的key有什么作用(key的内部原理)、(Vue) key值的作用等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/9843249.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-02
下一篇 2023-05-02

发表评论

登录后才能评论

评论列表(0条)

保存