vue的keep-alive组件的使用及其实现原理

2024-05-19 11:38

1. vue的keep-alive组件的使用及其实现原理

 keep-alive是Vue.js的一个内置组件。它能够把不活动的组件实例保存在内存中,而不是直接将其销毁,它是一个抽象组件,不会被渲染到真实DOM中,也不会出现在父组件链中。
   它提供了include与exclude两个属性,允许组件有条件地进行缓存。
   具体内容可以参考 官网 。
    用法 
   这里的component组件会被缓存起来。
    举个栗子 
   在点击button时候,coma与comb两个组件会发生切换,但是这时候这两个组件的状态会被缓存起来,比如说coma与comb组件中都有一个input标签,那么input标签中的内容不会因为组件的切换而消失。
    props 
   keep-alive组件提供了include与exclude两个属性来允许组件有条件地进行缓存,二者都可以用逗号分隔字符串、正则表达式或一个数组来表示。
   将缓存name为a的组件。
   name为a的组件将不会被缓存。
    生命钩子 
   keep-alive提供了两个生命钩子,分别是activated与deactivated。
   因为keep-alive会将组件保存在内存中,并不会销毁以及重新创建,所以不会重新调用组件的created等方法,需要用activated与deactivated这两个生命钩子来得知当前组件是否处于活动状态。
   说完了keep-alive组件的使用,我们从源码角度看一下keep-alive组件究竟是如何实现组件的缓存的呢?    created与destroyed钩子 
   created钩子会创建一个cache对象,用来作为缓存容器,保存vnode节点。
   destroyed钩子则在组件被销毁的时候清除cache缓存中的所有组件实例。
    render 
   首先通过getFirstComponentChild获取第一个子组件,获取该组件的name(存在组件名则直接使用组件名,否则会使用tag)。接下来会将这个name通过include与exclude属性进行匹配,匹配不成功(说明不需要进行缓存)则不进行任何操作直接返回vnode,vnode是一个VNode类型的对象,不了解VNode的同学可以参考笔者的另一篇文章 《VNode节点》  .
   检测include与exclude属性匹配的函数很简单,include与exclude属性支持字符串如"a,b,c"这样组件名以逗号隔开的情况以及正则表达式。matches通过这两种方式分别检测是否匹配当前组件。
   接下来的事情很简单,根据key在this.cache中查找,如果存在则说明之前已经缓存过了,直接将缓存的vnode的componentInstance(组件实例)覆盖到目前的vnode上面。否则将vnode存储在cache中。
   最后返回vnode(有缓存时该vnode的componentInstance已经被替换成缓存中的了)。
    watch 
   用watch来监听include与exclude这两个属性的改变,在改变的时候修改cache缓存中的缓存数据。
   来看一下pruneCache的实现。
   遍历cache中的所有项,如果不符合filter指定的规则的话,则会执行pruneCacheEntry。pruneCacheEntry则会调用组件实例的$destroy方法来将组件销毁。
   Vue.js内部将DOM节点抽象成了一个个的 VNode节点 , keep-alive组件的缓存也是基于VNode节点的而不是直接存储DOM结构。它将满足条件(include与exclude)的组件在cache对象中缓存起来,在需要重新渲染的时候再将vnode节点从cache对象中取出并渲染。 
   原文: 聊聊keep-alive组件的使用及其实现原理 

vue的keep-alive组件的使用及其实现原理

2. vue开启keep-alive需要注意的问题

  一、开启keep-alive 
   在这里keep-alive配合了router-view使用,keep-alive本身是vue2.0的功能,并不是vue-router的,所以在vue1.0版本是不支持的。
    二、产生的问题 
   keep-alive能使组件数据缓存,因此。如果有一个新闻列表,点击进入查看详情,返回点击查看其他新闻详情这时发现数据并没有更新,造成了数据不刷新的情况。   因此,我试了以下网友提出的解决方法,发现并没有什么用(或许是我弄错了)。
    三、我的解决方法 
   因此,个人拙见,我是这么解决的。在详情组件里监听路由变化再次赋值给ID,通过activated钩子触发请求函数,这时返回详情页面再次进入发现原有的数据还在,但是过几秒后数据就刷新了,数据是刷新了但是体验是非常不好的。因此需要用到另一个钩子deactivated销毁,离开详情页面时(deactivated)通过小技巧把当前的内容隐藏,再次进入详情页面时(activated)就不会看到原来的内容了,然后ajax请求数据完成后把它显示出来即可。    当引入keep-alive的时候,页面第一次进入,钩子的触发顺序created-> mounted-> activated,退出时触发deactivated。当再次进入(前进或者后退)时,只触发activated。 
    四、2019新发现    使用exclude属性不缓存模板组件即可,没有上面那么复杂了。

3. vue 缓存组件keep-alive

 kee-alive 是 Vue 内置的一个组件, 可以使被包含的组件保留状态,或避免重新渲染 。也就是所谓的组件缓存 
   keep-alive是一个抽象的组件,缓存的组件不会被mounted,为此提供activated和deactivated钩子函数   在2.1.0 版本后keep-alive新加入了两个属性: include(包含的组件缓存生效) 与 exclude(排除的组件不缓存,优先级大于include) 。
    keep-alive可以接收3个属性做为参数进行匹配对应的组件进行缓存: 
    include  包含的组件(可以为字符串,数组,以及正则表达式,只有匹配的组件会被缓存)
    exclude  排除的组件(以为字符串,数组,以及正则表达式,任何匹配的组件都不会被缓存)
    max  缓存组件的最大值(类型为字符或者数字,可以控制缓存组件的个数)
    配合router使用 
    1.keep-alive 先匹配被包含组件的 name 字段,如果 name 不可用,则匹配当前组件 components 配置中的注册名称。   2.keep-alive 不会在函数式组件中正常工作,因为它们没有缓存实例。   3.当匹配条件同时在 include 与 exclude 存在时,以 exclude 优先级最高(当前vue 2.4.2 version)。比如:包含于排除同时匹配到了组件A,那组件A不会被缓存。   4.包含在 keep-alive 中,但符合 exclude ,不会调用activated和 deactivated。 
   参考  https://juejin.cn/post/6844903918313406472    参考  https://www.imooc.com/article/302879 

vue 缓存组件keep-alive

4. Vue keep-alive防止重复渲染DOM总结

  一,VUE单页面应用文件实现返回上一页面时保留之前的数据 
    最近在做项目时,需要实现下面场景: 
   在页面查询列表,进入详情页时,返回时需要页面返回到上次浏览的位置(保留之前的当前页和搜索条件数据)
   针对上面的 需求:   页面的缓存,我们需要用到vue的内置组件 keep-alive ,来缓存列表页面,同时配合路由选项俩更改页面的数据   1.在路由出口渲染组件时配置:
    介绍一下  这个内置组件    是vue 的内置组件,能在组件切换过程中将状态保留在内存中,防止重复渲染DOM。     包裹动态组件时,而不是销毁他们。和  相似,  是一个抽象组件:他自身不会渲染一个DOM元素,也不会出现在父组件链中。     有两个属性:   (1) include :字符串或者正则表达式,只有匹配的组件会被缓存。    exclude :字符串或者正则表达式,任何匹配的组件都不会被缓存。   2.在需要做缓存的页面加上name
    注意需要缓存页面里的name里的名字 要和 include里的名字一致才会缓存。