vue基础知识十八:说说你对keep-alive的理解是什么?

在这里插入图片描述
一、Keep-alive 是什么

keep-alive是vue中的内置组件,能在组件切换过程中将状态保留在内存中,防止重复渲染DOM

keep-alive 包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们

keep-alive可以设置以下props属性:

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

关于keep-alive的基本用法:

<keep-alive>
  <component :is="view"></component>
</keep-alive>

使用includes和exclude:

<keep-alive include="a,b">
  <component :is="view"></component>
</keep-alive>

<!-- 正则表达式 (使用 `v-bind`) -->
<keep-alive :include="/a|b/">
  <component :is="view"></component>
</keep-alive>

<!-- 数组 (使用 `v-bind`) -->
<keep-alive :include="['a', 'b']">
  <component :is="view"></component>
</keep-alive>

匹配首先检查组件自身的 name 选项,如果 name 选项不可用,则匹配它的局部注册名称 (父组件 components 选项的键值),匿名组件不能被匹配

设置了 keep-alive 缓存的组件,会多出两个生命周期钩子(activated与deactivated):

  • 首次进入组件时:beforeRouteEnter > beforeCreate > created> mounted > activated > … … > beforeRouteLeave > deactivated
  • beforeRouteEnter >activated > … … > beforeRouteLeave > deactivated

二、使用场景

使用原则:当我们在某些场景下不需要让页面重新加载时我们可以使用keepalive

举个栗子:

当我们从首页–>列表页–>商详页–>再返回,这时候列表页应该是需要keep-alive

从首页–>列表页–>商详页–>返回到列表页(需要缓存)–>返回到首页(需要缓存)–>再次进入列表页(不需要缓存),这时候可以按需来控制页面的keep-alive

在路由中设置keepAlive属性判断是否需要缓存

{
  path: 'list',
  name: 'itemList', // 列表页
  component (resolve) {
    require(['@/pages/item/list'], resolve)
 },
 meta: {
  keepAlive: true,
  title: '列表页'
 }
}

使用

<div id="app" class='wrapper'>
    <keep-alive>
        <!-- 需要缓存的视图组件 --> 
        <router-view v-if="$route.meta.keepAlive"></router-view>
     </keep-alive>
      <!-- 不需要缓存的视图组件 -->
     <router-view v-if="!$route.meta.keepAlive"></router-view>
</div>

三、原理分析

keep-alive是vue中内置的一个组件

源码位置:src/core/components/keep-alive.js

export default {
  name: 'keep-alive',
  abstract: true,

  props: {
    include: [String, RegExp, Array],
    exclude: [String, RegExp, Array],
    max: [String, Number]
  },

  created () {
    this.cache = Object.create(null)
    this.keys = []
  },

  destroyed () {
    for (const key in this.cache) {
      pruneCacheEntry(this.cache, key, this.keys)
    }
  },

  mounted () {
    this.$watch('include', val => {
      pruneCache(this, name => matches(val, name))
    })
    this.$watch('exclude', val => {
      pruneCache(this, name => !matches(val, name))
    })
  },

  render() {
    /* 获取默认插槽中的第一个组件节点 */
    const slot = this.$slots.default
    const vnode = getFirstComponentChild(slot)
    /* 获取该组件节点的componentOptions */
    const componentOptions = vnode && vnode.componentOptions

    if (componentOptions) {
      /* 获取该组件节点的名称,优先获取组件的name字段,如果name不存在则获取组件的tag */
      const name = getComponentName(componentOptions)

      const { include, exclude } = this
      /* 如果name不在inlcude中或者存在于exlude中则表示不缓存,直接返回vnode */
      if (
        (include && (!name || !matches(include, name))) ||
        // excluded
        (exclude && name && matches(exclude, name))
      ) {
        return vnode
      }

      const { cache, keys } = this
      /* 获取组件的key值 */
      const key = vnode.key == null
        // same constructor may get registered as different local components
        // so cid alone is not enough (#3269)
        ? componentOptions.Ctor.cid + (componentOptions.tag ? `::${componentOptions.tag}` : '')
        : vnode.key
     /*  拿到key值后去this.cache对象中去寻找是否有该值,如果有则表示该组件有缓存,即命中缓存 */
      if (cache[key]) {
        vnode.componentInstance = cache[key].componentInstance
        // make current key freshest
        remove(keys, key)
        keys.push(key)
      }
        /* 如果没有命中缓存,则将其设置进缓存 */
        else {
        cache[key] = vnode
        keys.push(key)
        // prune oldest entry
        /* 如果配置了max并且缓存的长度超过了this.max,则从缓存中删除第一个 */
        if (this.max && keys.length > parseInt(this.max)) {
          pruneCacheEntry(cache, keys[0], keys, this._vnode)
        }
      }

      vnode.data.keepAlive = true
    }
    return vnode || (slot && slot[0])
  }
}

可以看到该组件没有template,而是用了render,在组件渲染的时候会自动执行render函数

this.cache是一个对象,用来存储需要缓存的组件,它将以如下形式存储:

this.cache = {
    'key1':'组件1',
    'key2':'组件2',
    // ...
}

在组件销毁的时候执行pruneCacheEntry函数

function pruneCacheEntry (
  cache: VNodeCache,
  key: string,
  keys: Array<string>,
  current?: VNode
) {
  const cached = cache[key]
  /* 判断当前没有处于被渲染状态的组件,将其销毁*/
  if (cached && (!current || cached.tag !== current.tag)) {
    cached.componentInstance.$destroy()
  }
  cache[key] = null
  remove(keys, key)
}

在mounted钩子函数中观测 include 和 exclude 的变化,如下:

mounted () {
    this.$watch('include', val => {
        pruneCache(this, name => matches(val, name))
    })
    this.$watch('exclude', val => {
        pruneCache(this, name => !matches(val, name))
    })
}

如果include 或exclude 发生了变化,即表示定义需要缓存的组件的规则或者不需要缓存的组件的规则发生了变化,那么就执行pruneCache函数,函数如下:

function pruneCache (keepAliveInstance, filter) {
  const { cache, keys, _vnode } = keepAliveInstance
  for (const key in cache) {
    const cachedNode = cache[key]
    if (cachedNode) {
      const name = getComponentName(cachedNode.componentOptions)
      if (name && !filter(name)) {
        pruneCacheEntry(cache, key, keys, _vnode)
      }
    }
  }
}

在该函数内对this.cache对象进行遍历,取出每一项的name值,用其与新的缓存规则进行匹配,如果匹配不上,则表示在新的缓存规则下该组件已经不需要被缓存,则调用pruneCacheEntry函数将其从this.cache对象剔除即可

关于keep-alive的最强大缓存功能是在render函数中实现

首先获取组件的key值:

const key = vnode.key == null? 
componentOptions.Ctor.cid + (componentOptions.tag ? `::${componentOptions.tag}` : '')
: vnode.key

拿到key值后去this.cache对象中去寻找是否有该值,如果有则表示该组件有缓存,即命中缓存,如下:

/* 如果命中缓存,则直接从缓存中拿 vnode 的组件实例 */
if (cache[key]) {
    vnode.componentInstance = cache[key].componentInstance
    /* 调整该组件key的顺序,将其从原来的地方删掉并重新放在最后一个 */
    remove(keys, key)
    keys.push(key)
} 

直接从缓存中拿 vnode 的组件实例,此时重新调整该组件key的顺序,将其从原来的地方删掉并重新放在this.keys中最后一个

this.cache对象中没有该key值的情况,如下:

/* 如果没有命中缓存,则将其设置进缓存 */
else {
    cache[key] = vnode
    keys.push(key)
    /* 如果配置了max并且缓存的长度超过了this.max,则从缓存中删除第一个 */
    if (this.max && keys.length > parseInt(this.max)) {
        pruneCacheEntry(cache, keys[0], keys, this._vnode)
    }
}

表明该组件还没有被缓存过,则以该组件的key为键,组件vnode为值,将其存入this.cache中,并且把key存入this.keys中

此时再判断this.keys中缓存组件的数量是否超过了设置的最大缓存数量值this.max,如果超过了,则把第一个缓存组件删掉

四、思考题:缓存后如何获取数据

解决方案可以有以下两种:

  • beforeRouteEnter
  • actived

beforeRouteEnter

每次组件渲染的时候,都会执行beforeRouteEnter

beforeRouteEnter(to, from, next){
    next(vm=>{
        console.log(vm)
        // 每次进入路由执行
        vm.getData()  // 获取数据
    })
},

actived

在keep-alive缓存的组件被激活的时候,都会执行actived钩子

activated(){
   this.getData() // 获取数据
},

注意:服务器端渲染期间avtived不被调用

小爱同学-Allen
关注 关注
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
vue 中的 keep-alive
weixin_39111384的博客
12-28 5351
一、什么是 Keep-alive keep-alivevue 中的内置组件,能够在组件切换过程中将状态保留在内存中,防止重复的渲染 DOM; keep-alive 包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们; keep-alive 可以设置一下 props 属性: include - 字符串或者是正则表达式。只有名称匹配的组件才能被缓存 exclude - 字符串或者是正则表达式。 max - 数字。最多可以缓存多少组件实例。 关于 keep-alive 的基本用法 <keep-
vue组件缓存之keep-alive正确使用姿势_keepalive缓存组件
最新发布
m0_46608024的博客
04-18 319
但是但是,我们的项目是用vue开发的webapp,多个组件共用一个窗口,当我们切换路由时,切出路由组件会销毁,所有列表页进入详情页列表页会销毁,重新回到列表页,列表页组件会重新加载。这样需求,如果是小程序的话,默认列表页就会缓存,因为小程序的运行环境是微信客户端,当我们打开一个页面会新建一个webview,所有列表页和详情页是两个webview,当我们进入详情页,列表页webview,只是会在详情页webview下面,不会销毁。从详情页返回,希望列表页缓存,不重新渲染数据,这样会提高用户体验。
谈谈你对keep-alive的了解
qq_41916791的博客
04-01 559
谈谈你对keep-alive的了解1. keep-alive是什么?2. keep-alive功能是什么?3. 使用场景 1. keep-alive是什么? 是vue系统自带的组件 2. keep-alive功能是什么? 是用来缓存组件的.==>提升性能 3. 使用场景 就是来缓存组件,提升项目性能,减少发送请求的数量. (具体实现比如:首页进入到详情页,如果用户在首页每次点击都是相同的,那么详情页就没必要请求N次了,直接缓存起来就可以了,当然,如果点击的不是同一个,那么就直接请求) .
谈谈keep-alive理解
qq_39872626的博客
04-14 4006
1、概念 keep-aliveVue的内置组件,当它包裹动态组件时,会缓存不活动的组件实例,而不是销毁。 2、功能 keep-alive是系统自带的一个组件,用来缓存组件,避免多次加载相同的组件,减少性能消耗,提高用户体验。 3、使用场景 列表页进入详情页,如果在列表页点击的都是相同的 ,详情页就不用请求多次了,直接缓存起来就行了,如果点击的不同,则需要重新请求数据。 4、使用方式 方式一:在App.vue中使用keep-alive标签,表示缓存所有页面 <div id="ap
[vue] 你对keep-alive理解是什么?
歌谣的博客
03-01 570
[vue] 你对keep-alive理解是什么? keep-aliveVue提供的一个抽象组件,用来对组件进行缓存,从而节省性能,由于是一个抽象组件,所以在页面渲染完毕后不会被渲染成一个DOM元素 个人简介 我是歌谣,欢迎和大家一起交流前后端知识。放弃很容易, 但坚持一定很酷。欢迎大家一起讨论 主目录 与歌谣一起通关前端面试题 ...
你对keep-alive理解
weixin_72502274的博客
12-05 168
前端面试必会
Vue基础知识.pptx
03-24
总的来Vue.js基础知识和进阶特性对于前端开发者来至关重要,熟练掌握这些知识点不仅能帮助面试者成功通过Vue相关的职位面试,而且在实际项目中也能发挥出强大的能力。通过不断学习和实践,开发者可以充分...
iview-admin不同路由使用keep-alive分别缓存
chisi9182的博客
08-13 1412
1 问题描述 自从使用iview-admin这个框架以来,长久有一个问题始终困扰着我,就是每次载入新路由(vue-router)时,总是会重新读取请求数据,这就引出了两个很严重的问题: 请求重复,响应速度慢(前者一般是后者的原因); 每次切换路由时,组件中的data都会重置(这在逻辑上很要命...
Vue基础知识梳理(二)
GTbond的博客
01-12 840
vue基础知识梳理(二) 1. vue中v-bind:class动态添加class 方案一:直接在html结构中给class一个对象 //html <div class="btn" :class="{wordColor:false,wordSize:true}" >点我</div> //样式 .btn{ width: 100px; height: 30px; line-height: 30px; text-align: center; b
Vue基础知识学习笔记
m0_46400711的博客
07-13 290
vue基础知识学习笔记 常用指令、计算属性、生命周期、动画、自定义过滤器、组件、路由、vue-cli等等。
你对keep-alive理解是什么?
Web_boom的博客
02-23 473
整理了75个JS高频面试题,并给出了答案和解析,基本上可以保证你能应付面试官关于JS的提问。
了解keep-alive
yrxnnn的博客
12-29 626
1.什么是keep-alive keep-aliveVue 的内置组件,当它包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们。keep-alive 是一个抽象组件:它自身不会渲染成一个 DOM 元素,也不会出现在父组件链中。 2.keep-alive的作用 在组件切换过程中 把切换出去的组件保留在内存中,防止重复渲染DOM,减少加载时间及性能消耗,提高用户体验性 3.keep-alive的生命周期函数 被包含在keep-alive中创建的组件,会多出两个生命周期来的两个钩子函数:activate
对于keep-alive理解
weixin_54167313的博客
06-01 980
介绍 keep-alivevue内置的一个组件,而这个组件的作用就是能够缓存不活动的组件,我们能够知道,一般情况下,一个路由在切换时会被销毁,之前的数据全部丢失,下次再访问这个组件时,需要重新创建,重新调接口,重新渲染,为了提高性能我们可以使用 keep-alive 把组件缓存起来,这样在组件切换时,这个组件并没有被销毁,下次访问时,可以就可以显示出来,而且原组件中数据还在。 把需要缓存的组件使用 keep-alive 套起来即可。比如:把所有路由页面都缓存起来,在切换时不销毁: <keep-ali
(34):keep-alive理解
weixin_46511008的博客
11-01 543
keep-alive理解 一、Keep-alive 是什么 1、keep-alivevue中的内置组件,能在组件切换过程中将状态保留在内存中,防止重复渲染DOM 2、keep-alive 包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们 3、keep-alive可以设置以下props属性: (1)include - 字符串或正则表达式。只有名称匹配的组件会被缓存 (2)exclude - 字符串或正则表达式。任何名称匹配的组件都不会被缓存 (3)max - 数字。最多可以缓存多少组件实例
谈谈你对keep-alive 的了解
weixin_59519449的博客
03-28 364
1. 是什么? vue 系统自带的一个组件, 功能: 是用来缓存组件的。====》提升性能 2.使用场景 : 就是用来缓存组件,提升项目的性能。 具体实现比如:首页进入详情页,如果用户在首页每次点击都是相同的,那么详情页就没必要请求N次了,直接缓存就可以了,当然如果点击的不是同一个,那么就直接请求就可以了 ...
谈谈你对 keep-alive 的了解?
weixin_51348217的博客
01-20 507
谈谈你对 keep-alive 的了解? keep-aliveVue内置的一个组件,可以使被包含的组件保留状态,避免重新渲染,其有以下特性: 一般结合路由和动态组件一起使用,用于缓存组件; 提供include和exclude属性,两者都支持字符串或正则表达式,include表示只有名称匹配的组件会被缓存,exclude表示任何名称匹配的组件都不会被缓存,其中exclude的优先级比include高; 对应的两个钩子函数activated和deactivated,当组件被激活时,触发钩子函数ac
谈谈你对 keep-alive 的了解
weixin_67340539的博客
06-14 131
谈谈你对 keep-alive 的了解
Vue中谈谈你对 keep-alive 的了解?
LuckXinXin的博客
03-23 438
答; keep-alive 可以缓存其它组件及其的组件的状态,避免了组件的频繁创建和销毁。 它有三个特性: 1.用于缓存组件,一般结合路由和动态组件一起使用。 2.提供 include 和 exclude 属性。两者都支持字符串或正则表达式, include 表示只有名称匹配的组件会被缓存,exclude 表示任何名称匹配的组件都不会被缓存 ,其中 exclude 的优先级比 include 高;...
Vue.js使用详解:组件、keep-alive与CSS隔离
学习并熟练掌握这些关键知识点,将有助于你更有效地构建Vue.js应用程序。在实际开发过程中,还应关注Vue.js的生命周期、计算属性、监听器、过渡效果等其他重要概念,以提升应用的功能性和性能。
写文章

热门文章

  • js将字符串转换成数字的四种方法 70147
  • vue如何获取当前页面的url 32346
  • Vue vue.config.js 的详解与配置 22822
  • 通过CSS实现 文字渐变色 的两种方式 13621
  • vue 实现pdf文件在线预览 13545

分类专栏

  • es6 9篇
  • webpack babel 2篇
  • javascript 2篇
  • 文件上传 1篇
  • uniapp 4篇
  • 小程序分包 1篇
  • computed 1篇
  • 移动端 1篇
  • 前端 11篇
  • css 1篇
  • flex 1篇
  • 原型链继承 2篇
  • nginx 2篇
  • input事件 1篇
  • 请求超时 1篇
  • 后端 1篇
  • java 1篇
  • 行内元素bug 1篇
  • table 1篇
  • table tr 1篇
  • vue路由 2篇
  • history 1篇
  • axios 1篇
  • div不可点击
  • 苹果手机 1篇
  • 小程序 1篇
  • vue组件通信 1篇
  • springboot数据增删改查 1篇
  • springboot入门一 1篇
  • vue.$set 1篇
  • vue-quill-editor 1篇
  • vue动态菜单 1篇
  • 后台配置路径错误,页面跳转到404 1篇
  • localStorage 1篇
  • css3 16篇

最新评论

  • 【uview calendar日历 】如何选择今天之前的数据

    double帅丢丢: uview 2.0 中使用<u-calendar 弹窗出来的日期,周几是错位的,今天是周四,显示了周三,大佬遇到过吗

  • vue-quill-editor上传内容由于图片是base64的导致字符太长的问题解决,把vue-quill-editor封装成组件

    路小雨的雨web: 编辑的时候怎么解决带标签问题的

  • 【uview calendar日历 】如何选择今天之前的数据

    小爱同学-Allen: 你这种情况,我后面也试下,我这边是设置今天之前或者今天之后,所以没遇到你说这个问题

  • 【uview calendar日历 】如何选择今天之前的数据

    小爱同学-Allen: 你这种情况,我后面也试下,我这边是设置今天之前或者今天之后,所以没遇到你说这个问题

  • 【uview calendar日历 】如何选择今天之前的数据

    jiaowoqiaodaima: uView提示:maxDate不能小于当前时间

大家在看

  • 详细描述一下一条SQL语句在MySQL中的执行过程 584
  • 【项目实战】如何在项目中基于 Spring Boot Starter 开发简单的 SDK 422
  • 自定义项目授权文件生成与认证 835
  • 《飞机大战游戏》实训项目(Java GUI实现)(设计模式)(简易) 835
  • springboot基于java的社区居民诊疗健康管理系统(源码+文档+调试+vue+前后端分离) 441

最新文章

  • vue基础知识十七:你知道vue中key的原理吗?说说你对它的理解
  • vue基础知识十六:Vue.observable你有了解过吗?说说看
  • vue基础知识十五:说说你对slot的理解?slot使用场景有哪些?
2023年119篇
2022年25篇
2021年26篇
2020年37篇
2019年13篇

目录

目录

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值

玻璃钢生产厂家长沙玻璃钢雕塑定制报价陕西创意玻璃钢雕塑多少钱山东户外商场美陈厂家直销云浮美陈玻璃钢雕塑深圳玻璃钢雕塑躺椅阿克苏玻璃钢雕塑厂宁波市玻璃钢雕塑洛阳专业校园玻璃钢景观雕塑西安玻璃钢雕塑厂电话玻璃钢雕塑维修方法长沙小区玻璃钢雕塑价格哈尔滨抽象玻璃钢雕塑ps玻璃钢雕塑效果太湖仿铜玻璃钢雕塑山东玻璃钢卡通雕塑玻璃钢艳后雕塑哪家好江门玻璃钢雕塑制品为什么雕塑用玻璃钢成都玻璃钢雕塑招聘信息北辰玻璃钢向日葵雕塑玻璃钢雕塑厂环评清远商场装饰玻璃钢卡通雕塑无锡玻璃钢龙雕塑设计商场拖鞋美陈道具重庆玻璃钢雕塑修补招聘玻璃钢花盆怎么销售商场美陈装饰有限公司福州玻璃钢雕塑方案仿铜玻璃钢雕塑多少钱仿铜玻璃钢雕塑行情香港通过《维护国家安全条例》两大学生合买彩票中奖一人不认账让美丽中国“从细节出发”19岁小伙救下5人后溺亡 多方发声单亲妈妈陷入热恋 14岁儿子报警汪小菲曝离婚始末遭遇山火的松茸之乡雅江山火三名扑火人员牺牲系谣言何赛飞追着代拍打萧美琴窜访捷克 外交部回应卫健委通报少年有偿捐血浆16次猝死手机成瘾是影响睡眠质量重要因素高校汽车撞人致3死16伤 司机系学生315晚会后胖东来又人满为患了小米汽车超级工厂正式揭幕中国拥有亿元资产的家庭达13.3万户周杰伦一审败诉网易男孩8年未见母亲被告知被遗忘许家印被限制高消费饲养员用铁锨驱打大熊猫被辞退男子被猫抓伤后确诊“猫抓病”特朗普无法缴纳4.54亿美元罚金倪萍分享减重40斤方法联合利华开始重组张家界的山上“长”满了韩国人?张立群任西安交通大学校长杨倩无缘巴黎奥运“重生之我在北大当嫡校长”黑马情侣提车了专访95后高颜值猪保姆考生莫言也上北大硕士复试名单了网友洛杉矶偶遇贾玲专家建议不必谈骨泥色变沉迷短剧的人就像掉进了杀猪盘奥巴马现身唐宁街 黑色着装引猜测七年后宇文玥被薅头发捞上岸事业单位女子向同事水杯投不明物质凯特王妃现身!外出购物视频曝光河南驻马店通报西平中学跳楼事件王树国卸任西安交大校长 师生送别恒大被罚41.75亿到底怎么缴男子被流浪猫绊倒 投喂者赔24万房客欠租失踪 房东直发愁西双版纳热带植物园回应蜉蝣大爆发钱人豪晒法院裁定实锤抄袭外国人感慨凌晨的中国很安全胖东来员工每周单休无小长假白宫:哈马斯三号人物被杀测试车高速逃费 小米:已补缴老人退休金被冒领16年 金额超20万

玻璃钢生产厂家 XML地图 TXT地图 虚拟主机 SEO 网站制作 网站优化