潇潇洒洒写一个KeepAlive动态缓存组件

大家好呀,我是wangly。一名不怎么摸鱼的前端小倒霉蛋。前端

这篇文章主要写了一下大部分Admin系统中常见的动态缓存组件,说通俗一点就是TagsBar组件。能够看下@panjiachen大佬Admin项目。集成在一完整项目中的组件或多或少会依赖一些其余的东西,这一次就开始从零实现这个功能吧。源码在底部,每一步都附待思路图哦。vue

效果图
效果图

开始

画了一张很水的图,其实整个过程很简单,进入页面路由后,判断当前路由是不是在白名单中,像登陆页面,404等页面是不须要被缓存的。只有后台管理系统的页面须要缓存,那么就将当前路由信息缓存到Vuex的缓存区。在经过缓存区的内容生成keep-aliveinclude的匹配条件。同时根据缓存区的内容生成标签。那么下面就开始吧git

流程图
流程图
效果演示图
效果演示图

进入路由后

为何不在进入页面前,个人考虑是,只有真正到达了路由了才算是进入页面。因此说,在路由的after钩子中进行操做。github

router.afterEach((to, from) => {
 // ... 判断是否在白名单  // ... 添加缓存区 }) 复制代码

是否在白名单

验证是不是一些在白名单的路由。像基本的登录页面,404时不要进行缓存的。所以须要过滤掉它。其次在经过一个Mutations方法changeCacheKeepMap修改和添加缓存的路由组件。web

router.afterEach((to, from) => {
 if (!whitePath.includes(to.path)) {  Store.commit('changeCacheKeepMap', to)  } }) 复制代码

添加到缓存区

vuex中的changeCacheKeepMap主要是对statecacheKeepMapMap数据进行一个操做。众所周知,Map是有序的。值是无重复的。在这里很是适合做为主要数据结构。在这里Mapkey设置为路由的名称。内容就是路由信息。须要注意的是,Vue对于Map的支持较差,因此只能直接从新覆盖原数据才能进行响应式。这里是一个坑点。vuex

路由名称 = 组件名称,这一步很重要。由于它是做为KeepAlive组件缓存的依据。没有这个依据,就上不了车。数组

/**  * 添加缓存组件信息  * @param {RouteConfig} route  */ changeCacheKeepMap(state, route) {  const swapMap = new Map(state.cacheKeepMap)  swapMap.set(route.name, route)  state.cacheKeepMap = swapMap } 复制代码
Vuex数据
Vuex数据

缓存router-view

经过keep-aliveinclude来进行组件缓存凭证。须要在缓存的页面中标明name属性。 filterIncludeComponentName计算属性主要是将Map存放的key所有汇聚成为一个数组。做为include的条件。缓存

// DOM
 <keep-alive :include="filterIncludeComponentName">  <router-view/> </keep-alive>  // filterIncludeComponentName计算属性 filterIncludeComponentName () {  const componentNames = []  for (const key of this.cacheKeepMap.keys()) {  componentNames.push(key)  }  return componentNames } 复制代码
缓存组件
缓存组件

include 使该标签做用于全部name属性的值跟此标签 include 的属性值一致的vue页面数据结构

顶部标签生成

这里就简单的多了,经过v-for遍历出Mapkeyvalue,很是的简单。而后设置标题,给route-link绑定to。经过当前路由的namelabel进行当前路由的判断。这里逻辑很是简单。编辑器

<router-link
 class="header-menu__item"  :to="value.path"  :class="$route.name === label && 'is-active'"  tag="li"  v-for="[label, value] in cacheKeepMap"  :key="label" >  <a-badge :status="$route.name === label ? 'processing' : 'default'" />  <span class="tag-text">{{value.meta.title}}</span>  <a-icon type="close" @click.stop="onCloseTag(label)" class="close-btn" /> </router-link>  复制代码

扩展...

还有须要扩展的功能对于你们来讲,是能够扩展的。好比清除缓存区,缓存区更新啥的。都是根据本身的需求来定义。若是你看完了文章,那么这些都难不住你。正所谓,知其一而知其三,方为学习。根据本身的思考,去扩展本身想要的功能,自己就是一种进步。

总结

本篇文章属于简单的技术分享文,若是对你有用,不妨给我点个赞吧。最近一直都是在看其余的资料,和准备编写一本小册。一些项目都懒散了。每周几篇文章总结仍是有的。之后会多多更新的。

下面附上源码地址给你们参考:

源码项目:连接

EleganceUI 求星星:连接

相关文章
相关标签/搜索