vuex + keep-alive实现tab标签页面缓存功能


Posted in Javascript onOctober 17, 2019

在开发很多管理系统过程之中,常遇到这种需求,需要对打开路由页面进行缓存,然后在系统页眉提供方便查阅的tab标签进行切换以及对已经缓存页面进行数据刷新和清除数据操作。具体演示如下图所示:

vuex + keep-alive实现tab标签页面缓存功能 

在上面演示中实现了类似 window tab 标签页效果,会对当前数据进行缓存。在浏览器中实现对路由页面的缓存可以减少接口请求,也方便了用户来回切换想搜索的数据列表。

原理

Vue 提供的 keep-alive API实现对路由组件的缓存。 include 属性可以绑定一个数组,里面是需要路由组件的 name 值,可以实现对该路由组件进行缓存,如果不需要对路由进行缓存,直接移除该项元素即可。

vuex + keep-alive实现tab标签页面缓存功能 

代码组织和设计

实现上面的功能,采用 vuex 进行全局的缓存数据保存,定义为 cacheView ;已经打开的路由页面用 toolBarData 进行保存。下图是代码是代码设计整体图:

vuex + keep-alive实现tab标签页面缓存功能 

需要添加一个路由页面到 cacheView ,需要有 actions setCacheView 来 commit 一个 change Event 对 state 数据进行更改,然后修改后的数据会自动派发到 App.vue 中使用到该数据的位置(即 keep-alive
处)。而添加标签页也是类似的流程,不再描述。至于为什么要把标签页和路由缓存页面分离成两个数组,主要是有两方面的考虑:

name

store代码实现

store 代码实现如下所示,主要需要比较详细说明的是 clearToolItem ,这个函数是清除标签页。涉及两个规则:

如果关闭是当前处于激活的标签页,关闭之后。处于激活的标签页就默认是最后一个打开的标签页。

如果当前标签页是最后一个(处于激活状态),则关闭后自动默认它的前一个为默认激活标签页。

import router from '../router'
export default {
  state: {
    toolBarData:[],// 保存标签button的数组
    cacheView:[] // 保存需要缓存的数组
  },
  getters: {
    getToolData(state){
      return state.toolBarData;
    },
    getCacheView(state){
      return state.cacheView;
    }
  },
  mutations: {
    setToolData(state, data) { // 添加标签按钮,如果当前路由已经打开,则不再重复添加
      const inToolbar = state.toolBarData.find(item => item.detail === data.detail)
      !inToolbar && state.toolBarData.push({
        ...data
      });
    },
    setCacheView(state,data){ // 与setToolData类似
      if(state.cacheView.includes(data.componentName)) 
        return;
      state.cacheView.push(data.componentName);
    },
    clearToolItem(state,detail){
      const index = state.toolBarData.findIndex(item => item.detail === detail);
      const isActive = router.app.$route.path == state.toolBarData[index]["detail"];
      const len = state.toolBarData.length - 1;
      state.toolBarData.splice(index,1);
      (index == len || isActive) && router.push({path:state.toolBarData[state.toolBarData.length - 1]["detail"]});
    },
    clearCacheView(state,viewName){
      const index = state.cacheView.findIndex(item => item == viewName);
      state.cacheView.splice(index,1);
    }
  },
  actions: {
    commitToolBar({commit},data) {
      commit("setToolData",data);
      commit("setCacheView",data);
    },
    clearToolBar({commit},data){
      commit("clearToolItem",data.detail);
    },
    clearCache({commit},data){
      commit("clearCacheView",data);
    }
  }
}

入口文件缓存路由

在 App.vue 入口文件,使用 keep-alive 对匹配的路由组件进行缓存,监听当前路由变化,添加缓存路由和标签。

<template>
  <el-main style="position:relative;margin-top:45px;">
    <!--渲染标签的地方-->
    <ToolBar></ToolBar>
    <div class="routeWrap">
      <transition name="fade-transform">
        <keep-alive :include="cachedViews">
          <router-view></router-view>
        </keep-alive>
      </transition>
    </div>
  </el-main>
 </template>
 <script>
  export default {
    watch: {
      $route() {
      // 路由组件名称(自定义)
       const componentName =this.$route.matched[0]["components"]["default"][ "name"];
       const detail = this.$route.path;
       // 当前路由匹配到name
       const name = this.$route.meta[0]["name"];
       this.$store.dispatch("commitToolBar", { name, detail, componentName });
      }
    }
  }
 </script>

ToolBar代码

这里使用了 elementui 的 el-tag 标签, el-tag 标签带有动画、关闭按钮、主题color等属性, close 函数是清除该标签和清除缓存路由(已访问过)。 click 主要是当对该标签项点击操作,则切换到该路由页面。其中 active 是该标签匹配到当前路由时候处于激活状态(颜色高亮), el-tag 的动画比较生硬,所以关闭了。

<template>
 <div class="toolbar">
  <el-tag
   class="toolItem"
   type="info"
   :disable-transitions="false"
   :closable="item.id != 0"
   effect="plain"
   v-for="(item,index) in getToolData"
   :key="index"
   :class="{active:$route.path == item.detail}"
   @click="redirect(item)"
   @close="closeToolItem(item)"
  >
   <span class="dot" v-if="$route.path == item.detail"></span>
   {{item.name}}
  </el-tag>
 </div>
</template>

<script>
import { mapGetters } from "vuex";
export default {
 methods: {
  closeToolItem(item, index) {
   this.$store.dispatch("clearToolBar", item);
   this.$store.dispatch("clearCache", item.componentName);
  },
  redirect(item) {
   this.$router.push({ path: item.detail });
  }
 },
 computed: {
  ...mapGetters(["getToolData", "getCacheView"])
 }
};
</script>

生命周期 activated 和 deactivated

采用了 keep-alive 缓存的路由组件,重新进入该路由,路由组件不会重新创建,所以也就不会触发组件的生命周期函数(比如说 beforeCreate 、 mounted 等)。所以在对该页面进行数据更新或者清除数据。 vue 为我们提供了 activated 和 deactivated 生命周期函数,当重新进入路由组件会触发 activated 函数,离开则会触发 deactivated 。

<template>
  <div> A page</div>
</template>
<script>
  export default {
    data(){
      return {
        form :{
          name:'',
          password:''
        }
      }
    },
    activated(){
      this.getList()
    },
    deactivated(){
      Object.keys(this.form).map(key => {
        this.form[key] = ''
      })
    }
  }
</script>

总结

以上所述是小编给大家介绍的vuex + keep-alive实现tab标签页面缓存问题,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!

Javascript 相关文章推荐
使用jquery插件实现图片延迟加载技术详细说明
Mar 12 Javascript
关于js类的定义
Jun 28 Javascript
使用Jquery实现点击文字后变成文本框且可修改
Sep 21 Javascript
21个JavaScript事件(Events)属性汇总
Dec 02 Javascript
JavaScript中toString()方法的使用详解
Jun 05 Javascript
Java框架SSH结合Easyui控件实现省市县三级联动示例解析
Jun 12 Javascript
AngularJS API之copy深拷贝详解及实例
Sep 14 Javascript
BootStrap select2 动态改变值的方法
Feb 10 Javascript
jqGrid翻页时数据选中丢失问题的解决办法
Feb 13 Javascript
jQuery自定义多选下拉框效果
Jun 19 jQuery
浅谈angular2路由预加载策略
Oct 04 Javascript
vue router 跳转后回到顶部的实例
Aug 31 Javascript
Weex开发之地图篇的具体使用
Oct 16 #Javascript
WEEX环境搭建与入门详解
Oct 16 #Javascript
Weex开发之WEEX-EROS开发踩坑(小结)
Oct 16 #Javascript
适合前端Vue开发童鞋的跨平台Weex的使用详解
Oct 16 #Javascript
微信公众号开发之微信支付代码记录的实现
Oct 16 #Javascript
关于JS模块化的知识点分享
Oct 16 #Javascript
vue-cli+iview项目打包上线之后图标不显示问题及解决方法
Oct 16 #Javascript
You might like
全国FM电台频率大全 - 10 江苏省
2020/03/11 无线电
使用PHP制作新闻系统的思路
2006/10/09 PHP
通过table标签,PHP输出EXCEL的实现方法
2013/07/24 PHP
php利用cookies实现购物车的方法
2014/12/10 PHP
微信自定义菜单的创建/查询/取消php示例代码
2016/08/05 PHP
利用Homestead快速运行一个Laravel项目的方法详解
2017/11/14 PHP
php实例化一个类的具体方法
2019/09/19 PHP
laravel实现上传图片并在页面显示的例子
2019/10/14 PHP
Laravel jwt 多表(多用户端)验证隔离的实现
2019/12/18 PHP
Thinkphp 框架配置操作之配置加载与读取配置实例分析
2020/05/15 PHP
基于php解决json_encode中文UNICODE转码问题
2020/11/10 PHP
javascript 用原型继承来实现对象系统
2010/03/22 Javascript
表单序列化与jq中的serialize使用示例
2014/02/21 Javascript
深入理解JavaScript系列(37):设计模式之享元模式详解
2015/03/04 Javascript
js文本框走动跑马灯效果代码分享
2015/08/25 Javascript
使用JQuery实现Ctrl+Enter提交表单的方法
2015/10/22 Javascript
JavaScript给input的value赋值引发的关于基本类型值和引用类型值问题
2015/12/07 Javascript
利用jquery实现验证输入的是否是数字、小数,包含保留几位小数
2016/12/07 Javascript
nodejs和C语言插入mysql数据库乱码问题的解决方法
2017/04/14 NodeJs
解决webpack -p压缩打包react报语法错误的方法
2017/07/03 Javascript
Three.js如何用轨迹球插件(trackball)增加对模型的交互功能详解
2017/09/25 Javascript
玩转Koa之koa-router原理解析
2018/12/29 Javascript
python调用Delphi写的Dll代码示例
2017/12/05 Python
python图像和办公文档处理总结
2019/05/28 Python
python单线程下实现多个socket并发过程详解
2019/07/27 Python
django将网络中的图片,保存成model中的ImageField的实例
2019/08/07 Python
Python+opencv+pyaudio实现带声音屏幕录制
2019/12/23 Python
英国泰坦旅游网站:全球陪同游览,邮轮和铁路旅行
2016/11/29 全球购物
HUGO BOSS美国官方网上商店:世界知名奢侈品牌
2017/08/04 全球购物
波兰香水和化妆品购物网站:Notino.pl
2017/11/07 全球购物
老板电器官方购物商城:老板油烟机、燃气灶、消毒柜、电烤箱
2018/05/30 全球购物
先进学校事迹材料
2014/12/30 职场文书
五星级酒店前台接待岗位职责
2015/04/02 职场文书
2016年学校党支部公开承诺书
2016/03/25 职场文书
《成长的天空》读后感3篇
2019/12/06 职场文书
利用Python实现模拟登录知乎
2022/05/25 Python