vue3-ts:keepalive 列表页到详情,详情回到列表,列表恢复离开时的状态

news/2024/7/10 1:53:30 标签: 前端, keepalive, vue

一、KeepAlive简介

技术栈:vue3 + ts + pinia

<KeepAlive> 是一个内置组件,它的功能是在多个组件间动态切换时缓存被移除的组件实例。

keepalive组件总共有三个参数

include:可传字符串、正则表达式、数组,名称匹配成功的组件会被缓存

exclude:可传字符串、正则表达式、数组,名称匹配成功的组件不会被缓存

max:可传数字,限制缓存组件的最大数量,默认为10

include包含的 && 排除exclude包含的 就是需要缓存的组件

<keep-alive :include="" :exclude="" :max=""></keep-alive>

二、使用场景

在列表页面 点击查看 路由到详情页面
详情页面点击返回,希望回到当时从列表页面离开时的样子
(因为列表页经过了tab切换,表单查询,分页查询等操作,如果回到列表页是一个初始的状态,那么需要重新操作这一系列动作)

三、全局实现keepalive

3.1、App.vue

<template>
  <!-- <router-view></router-view> -->
  <router-view v-slot="{ Component }">
    <keep-alive>
      <component :is="Component" />
    </keep-alive>
  </router-view>
</template>
<script setup lang="ts">
onErrorCaptured(err => {
  console.log('Caught error', err)
  return false
})
</script>
<style scoped>
</style>

3.2、src/views/keepaliva/index.vue

<template>
  <div class="container">
    <div>keep-alive</div>
    <div>
      <el-input v-model="KValue"></el-input>
    </div>
    <div>
      <router-link to='/keepalive-snow'>
        <button>keep-aliva-snow</button>
      </router-link>
    </div>
  </div>
</template>
<script setup lang="ts">
const KValue = ref('')

</script>

<style scoped lang="less">
</style>

3.3、src/views/keepaliva/snow.vue

<template>
  <div class="container">
    <div>keep-alive</div>
    <div>
      <el-input v-model="KValue"></el-input>
    </div>
    <div>
      <router-link to='/keepalive'>
        <button>keep-aliva</button>
      </router-link>
    </div>
  </div>
</template>
<script setup lang="ts">
const KValue = ref('')

</script>

<style scoped lang="less">
</style>

至此,简单的keepalive demo已实现。生产项目使用肯定不能这么暴力,本文继续介绍其他内容以满足生产使用。

四、router配置缓存

4.1、App.vue

<template>
  <!-- <router-view></router-view> -->
  <router-view v-slot="{ Component }">
    <component :is="Component" v-if="!$route.meta.keepAlive" :key="$route.path" />
    <keep-alive>
      <component :is="Component" v-if="$route.meta.keepAlive" :key="$route.path" />
    </keep-alive>
  </router-view>
</template>
<script setup lang="ts">
onErrorCaptured(err => {
  console.log('Caught error', err)
  return false
})
</script>
<style scoped>
.logo {
  height: 6em;
  padding: 1.5em;
  will-change: filter;
}
.logo:hover {
  filter: drop-shadow(0 0 2em #646cffaa);
}
.logo.vue:hover {
  filter: drop-shadow(0 0 2em #42b883aa);
}
</style>

4.2、src/routers/index.vue

{
    path: '/keepalive', // keepalive
    component: ()=>import('../views/keepalive/index.vue'),
    meta: {
      keepAlive: true // 该页面需要keepAlive
    }
  },
  {
    path: '/keepalive-snow', // keepalive
    component: ()=>import('../views/keepalive/snow.vue'),
    meta: {
      keepAlive: true // 该页面需要keepAlive
    }
  },

4.3、src/views/keepaliva/index.vue

<template>
  <div class="container">
    <div>keep-alive</div>
    <div>
      <el-input v-model="KValue"></el-input>
    </div>
    <div>
      <router-link to='/keepalive-snow'>
        <button>keep-aliva-snow</button>
      </router-link>
    </div>
  </div>
</template>

<script setup lang="ts">

const KValue = ref('')

onActivated(() => {
  // 调用时机为首次挂载
  // 以及每次从缓存中被重新插入时
  console.log('a-onActivated')
})

onDeactivated(() => {
  // 在从 DOM 上移除、进入缓存
  // 以及组件卸载时调用
  console.log('a-onDeactivated')
})

</script>

<style scoped lang="less">

</style>

4.4、src/views/keepaliva/snow.vue

<template>
  <div class="container">
    <div>keep-alive-snow</div>
    <div>
      <el-input v-model="KValue"></el-input>
    </div>
    <div>
      <router-link to='/keepalive'>
        <button>keep-aliva</button>
      </router-link>
    </div>
  </div>
</template>

<script setup lang="ts">

const KValue = ref('')

onActivated(() => {
  // 调用时机为首次挂载
  // 以及每次从缓存中被重新插入时
  console.log('b-onActivated')
})

onDeactivated(() => {
  // 在从 DOM 上移除、进入缓存
  // 以及组件卸载时调用
  console.log('b-onDeactivated')
})

</script>

<style scoped lang="less">

</style>

五、layouts配置keepalive--router配置

5.1、src/routers/index.vue

  {
    path: '/menu', // keepalive
    component: layout_menu,
    name: 'menu',
    children: [
      {
        path: 'keepalive',
        component: ()=>import('../views/keepalive/index.vue'),
        name: 'keepalive',
        meta: {
          keepAlive: true // 该页面需要keepAlive
        }
      }
    ],
    meta: {
      keepAlive: true // 该页面需要keepAlive
    }
  },
  {
    path: '/menu', // keepalive
    component: layout_menu,
    name: 'menu2',
    children: [
      {
        path: 'keepalivesnow',
        component: ()=>import('../views/keepalive/snow.vue'),
        name: 'keepalivesnow',
        meta: {
          keepAlive: true // 该页面需要keepAlive
        }
      }
    ],
    meta: {
      keepAlive: true // 该页面需要keepAlive
    }
  },

5.2、layouts/menu/index.vue

<!-- src/layouts/default/index.vue -->
<template>
    <el-container>
      <el-container>
        <el-header>
          <el-button @click="tomenu1">menu1</el-button>
          <el-button @click="tomenu2">menu2</el-button>
        </el-header>
        <el-main>
          <!-- 子路由出口 -->
          <!-- <router-view /> -->
          <router-view v-slot="{ Component }">
            <component :is="Component" v-if="!$route.meta.keepAlive" :key="$route.path" />
            <keep-alive>
              <component :is="Component" v-if="$route.meta.keepAlive" :key="$route.path" />
            </keep-alive>
          </router-view>
        </el-main>
      </el-container>
    </el-container>
  </template>
  
  <script setup lang="ts">
  import { useRouter } from "vue-router"
  const router = useRouter()
  const tomenu1 = ()=>{
    router.push({
      path: '/menu/keepalive'
    })
  }
  const tomenu2 = ()=>{
    console.log('28')
    router.push({
      path: '/menu/keepalivesnow'
    })
  }

  </script>
  
  <style scoped lang="less">
  .el-container {
    height: 100vh;
  }
  .el-header {
    background-color: #B3C0D1;
    color: #ff0000;
  }
  .el-main {
    background-color: #E9EEF3;
  }
  </style>

六、layouts配置keepalive--组件配置--推荐方法

本方法实现在layout文件配置keepalive,思路与方法满足生产环境使用。
点击菜单时候清空所有缓存的组件,点击查看时候缓存对应的组件,满足spa单页面项目生产使用。
实现在列表页经过一系列操作后,点查看到详情页,点返回回到列表页--列表页恢复离开时的状态,点击菜单恢复到没有缓存的页面展示最新的数据。推荐使用。

6.1、参数介绍

include:可传字符串、正则表达式、数组,名称匹配成功的组件会被缓存

exclude:可传字符串、正则表达式、数组,名称匹配成功的组件不会被缓存

max:可传数字,限制缓存组件的最大数量,默认为10

include包含的 && 排除exclude包含的 就是需要缓存的组件

6.2、layouts/menu/index.vue

<!-- src/layouts/default/index.vue -->
<template>
    <el-container>
      <el-container>
        <el-header>
          <el-button @click="toList">列表页</el-button>
          <el-button @click="toDetail">详情页</el-button>
          <el-button @click="clearPinia">恢复KeepAlive</el-button>
        </el-header>
        <el-main>
          <!-- 子路由出口 -->
          <!-- <router-view /> -->
          <router-view v-slot="{ Component }">
            <keep-alive :include="includeArr" :exclude="excludeArr" :max="10">
              <component :is="Component" :key="$route.path" />
            </keep-alive>
          </router-view>
        </el-main>
      </el-container>
    </el-container>
  </template>
  
  <script setup lang="ts">
  import { useRouter } from "vue-router"
  import { useKeepStore } from '@/views/stores/keepalive'
  const keepStoreData = useKeepStore()
  // 这里需要使用computed,否则清空excludeArr不起作用
  let includeArr = computed(()=>{
    return keepStoreData.includeArr
  })
  // 这里需要使用computed,否则清空excludeArr不起作用
  let excludeArr = computed(()=>{
    return keepStoreData.excludeArr
  })
  const router = useRouter()
  const toList = ()=>{
    keepStoreData.includeArr = []
    router.push({
      path: '/menu/keepalive'
    })
  }
  const toDetail = ()=>{
    keepStoreData.includeArr = []
    router.push({
      path: '/menu/keepalivesnow'
    })
  }
  const clearPinia = ()=>{
    keepStoreData.includeArr = ['keepalive','keepalivesnow']
  }
  </script>
  
  <style scoped lang="less">
  .el-container {
    height: 100vh;
  }
  .el-header {
    background-color: #B3C0D1;
    color: #ff0000;
  }
  .el-main {
    background-color: #E9EEF3;
  }
  </style>

6.3、 设置name

6.3.1安装插件

vite-plugin-vue-setup-extend

6.3.2、vite.config.ts 

引入插件

import VueSetupExtend from 'vite-plugin-vue-setup-extend'

使用插件

plugins: [vue(),VueSetupExtend()],

6.3.3、页面使用

<script setup lang="ts" name="keepalive">

6.4、src/routers/index.vue

同文本 5.1

6.5、src/views/keepaliva/index.vue

<template>
  <div class="container">
    <div>keep-alive-list-列表页面</div>
    <div>
      <span>接口数据:</span>
      <span v-for="(item, index) in nameList" :key="index">{{ item }}</span>
    </div>
    <div class="keep-table">
      <el-table :data="tableData" style="width: 500px">
        <el-table-column prop="name" label="Name" width="180" />
        <el-table-column prop="address" label="Address" />
      </el-table>
    </div>
    <div class="keep-pagination">
      <el-pagination
        layout="prev, pager, next"
        v-model:current-page="currentPage"
        :page-size="1"
        :total="total"
        @current-change="handleCurrentChange"
      />
    </div>
    <div>
      <span>输入框:</span>
      <el-input v-model="KValue"></el-input>
    </div>
    <div>
      <!-- <router-link to='/menu/keepalivesnow'>
        <button>查看详情页keep-aliva-details</button>
      </router-link> -->
      <button @click="toList">查看详情页keep-aliva-details</button>
      <button @click="getTableList('add1')">获取表格数据</button>
    </div>
  </div>
</template>

<script setup lang="ts" name="keepalive">
import { useRouter } from "vue-router"
import { useKeepStore } from '@/views/stores/keepalive'
import { getCurrentInstance } from 'vue'
const router = useRouter()
let keepStoreData = useKeepStore()
const KValue = ref('')
// 跳转详情
const toList = ()=>{
    keepStoreData.includeArr = ['keepalive']
    router.push({
      path: '/menu/keepalivesnow'
    })
  }
// 表格
let tableData = ref([])
let total = ref(2)
let currentPage = ref(1)
const handleCurrentChange = (val:number)=>{
  console.log('81',val)
}
// 测试接口
let internalInstance = getCurrentInstance();
let Api = internalInstance && internalInstance.appContext.config.globalProperties.$api
let params = {}
let nameList = ref([])
let getTableList = (add:string)=>{
  Api.getVideoList(params).then((res: any)=>{
    nameList.value = res.payload || []
    tableData.value = res.payload.map((item:any)=>{
      return {
        name: item,
        address: add
      }
    })
  })
}
getTableList('add2')
// keep生命周期
onActivated(() => {
  // 调用时机为首次挂载
  // 以及每次从缓存中被重新插入时
  console.log('a-onActivated')
})
onDeactivated(() => {
  // 在从 DOM 上移除、进入缓存
  // 以及组件卸载时调用
  console.log('a-onDeactivated')
})
</script>

<style scoped lang="less">
.el-input{
  width: 300px;
}
.keep-table{
  display: flex;
  justify-content: center;
}
.keep-pagination{
  display: flex;
  justify-content: center;
}
</style>

6.6、src/views/keepaliva/snow.vue

<template>
  <div class="container">
    <div>keep-alive-snow-详情页面</div>
    <div>
      <span>输入框:</span>
      <el-input v-model="KValue"></el-input>
    </div>
    <div>
      <router-link to='/menu/keepalive'>
        <button>回到列表页keep-aliva-list</button>
      </router-link>
    </div>
  </div>
</template>

<script setup lang="ts" name="keepalivesnow">
const KValue = ref('')
onActivated(() => {
  // 调用时机为首次挂载
  // 以及每次从缓存中被重新插入时
  console.log('b-onActivated')
})
onDeactivated(() => {
  // 在从 DOM 上移除、进入缓存
  // 以及组件卸载时调用
  console.log('b-onDeactivated')
})
</script>

<style scoped lang="less">
.el-input{
  width: 300px;
}
</style>

6.7、页面测试 name为keepalive的组件已被缓存,点击菜单清除缓存获取最新数据,测试成功。

七、onActivated、onDeactivated

onActivated:进入页面

onDeactivated:离开页面

八、C知道

问:vue3 keepalive使用详解

答:
Vue3 中的 keep-alive 组件是用于缓存动态组件的,可以在组件切换时保留组件的状态和避免重新渲染。下面是关于 Vue3 keep-alive 的使用详解:

基本使用
在需要缓存的组件外部包裹一个 <keep-alive> 标签,将需要缓存的组件放在其中:

<template>
  <keep-alive>
    <router-view />
  </keep-alive>
</template>
缓存的组件生命周期钩子函数
当一个组件被缓存时,它的生命周期钩子函数会有所不同。具体如下:

activated: 缓存的组件被激活时调用,可以在这里执行一些需要在组件激活时执行的操作。
deactivated: 缓存的组件被停用时调用,可以在这里执行一些需要在组件停用时执行的操作。

<template>
  <keep-alive>
    <router-view v-slot="{ Component }">
      <component :is="Component" />
    </router-view>
  </keep-alive>
</template>
在缓存的组件中添加 activated 和 deactivated 钩子函数:

<script>
export default {
  name: 'cached-component',
  activated() {
    console.log('cached-component activated')
  },
  deactivated() {
    console.log('cached-component deactivated')
  },
}
</script>
include 和 exclude 属性
include 和 exclude 属性可以用来控制 keep-alive 缓存哪些组件和排除哪些组件。它们都可以传递一个字符串或正则表达式的数组。

include:只有在 include 数组中的组件才会被缓存。
exclude:在 exclude 数组中的组件不会被缓存。

<template>
  <keep-alive include="home, about">
    <router-view v-slot="{ Component }">
      <component :is="Component" />
    </router-view>
  </keep-alive>
</template>
max 属性
max 属性用于设置缓存的最大组件数,当缓存的组件数量超过最大值时,最早缓存的组件会被销毁。

<template>
  <keep-alive max="10">
    <router-view v-slot="{ Component }">
      <component :is="Component" />
    </router-view>
  </keep-alive>
</template>

相关内容

1、通过url记录列表页的关键信息,查询条件、分页等

2、通过sessionStorage记录列表页的关键信息,查询条件、分页等

session只能在同一个页面起作用,所以复制一个链接打开后,对原来正常的操作的页面没有影响

3、keepalive--本文

过程记录

记录一、

Uncaught (in promise) TypeError: parentComponent.ctx.deactivate is not a function

 解决:

参考链接:

vue3中一些简单的小技巧_vite-plugin-vue-setup-extend_还一激灵的博客-CSDN博客

vue3 keep-alive 页面切换不触发onActivated和onDeactivated方法周期_vue3 onactivated_凯扣叮~的博客-CSDN博客

学习Vue3 第二十章(keep-alive缓存组件)_keep-live vue3 activated_小满zs的博客-CSDN博客

Vue3知识点_onactivated_阿信呐的博客-CSDN博客

如何在vue3的jsx中使用keep-alive? - 知乎

https://ask.csdn.net/questions/7727011

https://www.cnblogs.com/lyt0207/p/16543867.html

Vue3 keep-alive 缓存问题_ZL随心的博客-CSDN博客

https://www.cnblogs.com/aehyok/p/16328765.html

https://free_pan.gitee.io/router-tabs-wk/

vue3基于Element Plus和vue-router实现选项卡-多标签组件_哔哩哔哩_bilibili

【VUE面试题】vue2和vue3中使用keep-alive的区别_哔哩哔哩_bilibili

vue3的keep-alive组件使用详解(包含手动控制缓存清除)_哔哩哔哩_bilibili


http://www.niftyadmin.cn/n/182307.html

相关文章

linux入门---三个操作系统调用接口

getpid 在内存中的每个进程都有一个属于自己的PID&#xff0c;我们可以通过ps ajx指令查看进程的基本属性从而查看一个进程的pid&#xff0c;那么这里我们就可以创建一个文件然后往里面写入一个死循环的代码&#xff0c;再创建一个makefile文件在里面实现一些基本的功能&#…

MySQL-配置优化

目录 &#x1f341;连接请求的变量 &#x1f342;max_connections &#x1f342;back_log &#x1f342;wait_timeout和interactive_timeout &#x1f341;缓冲区变量 &#x1f342;key_buffer_size &#x1f342;query_cache_size &#x1f342;max_connect_errors &#x1f3…

【创作赢红包】求最大公因数与最小公倍数

什么是最小公因数 最大公约数&#xff08;Greatest Common Divisor&#xff09;指两个或多个整数共有约数中最大的一个。也称最大公因数、最大公因子&#xff0c;a&#xff0c; b的最大公约数记为&#xff08;a&#xff0c;b&#xff09;&#xff0c;同样的&#xff0c;a&…

服务器版RstudioServer安装与配置详细教程

Docker部署Rstudio server 背景&#xff1a;如果您想在服务器上运行RstudioServer&#xff0c;可以按照如下方法进行操作&#xff0c;笔者测试时使用腾讯云服务器&#xff08;系统centos7&#xff09;&#xff0c;需要在管理员权限下运行 Rstudio 官方提供了使用不同 R 版本的 …

Mybatis-Plus进阶使用

一、逻辑删除 曾经我们写的删除代码都是物理删除。 逻辑删除&#xff1a;删除转变为更新 update user set deleted1 where id 1 and deleted0 查找: 追加 where 条件过滤掉已删除数据,如果使用 wrapper.entity 生成的 where 条件也会自动追加该字段 查找: select id,name,dele…

反光板导航SLAM(四)如何通过两个反光柱估计位姿

通常而言确定空间中的一个点的坐标需要三个点&#xff0c;也就是俗称的三点定位。但是在某些时候&#xff0c;场景内可能不一定能够采样到足够多的反光柱&#xff0c;比如只有两个。这个时候看起来似乎参数是不足的&#xff0c;毕竟机器人的参数有三个&#xff0c;两个方程是不…

个人练习-Leetcode-89. Gray Code

题目链接&#xff1a;https://leetcode.cn/problems/gray-code/submissions/ 题目大意&#xff1a;给出位数n&#xff0c;求一个合法的n位格雷码排列。 思路&#xff1a;低位数的格雷码是容易得出的&#xff0c;考虑从n-1位的格雷码得到n位格雷码。设现有Gn−1G_{n-1}Gn−1​…

关于前端工具layui的一些使用总结

说明&#xff1a; 最近小组在做一个自研的字节码增强工具。因为是预研性质&#xff0c;所以前端的操作界面就自己上手写了。使用了比较亲和后端开发的layui框架。后端采用springbootthymeleaf 后端配置静态资源和thymeleaf&#xff1a; application.yml&#xff1a; 静态资源…