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

44 篇文章 0 订阅
43 篇文章 0 订阅

导图

 效果图

 相关代码

vuex的代码
01-getters.js
  getToolData(state){
        return state.toolBarData;
    },
    getCacheView(state){
        return state.cacheView;
    },
02-actions.js
export const actions = {
    commitToolBar({commit},data) {
        commit("setToolData",data);
        commit("setCacheView",data);
    },
    clearToolBar({commit},data){
        commit("clearToolItem",data.detail);
    },
    clearCache({commit},data){
        commit("clearCacheView",data);
    }
}
03-mutations.js
import router from './../router'
export const 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);
    },
}

CommonTools.vue
<template>
  <div class="commonToolsWrap" v-if="getToolData&&getToolData.length">
     <div class="commonTools">
          <el-tag
            class="tabToolItem"
            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>
          <span class="txt">{{item.name}}</span>
          </el-tag>
     </div>
  </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"])
  },
  watch: {
    // 监听路由变化自动dispatch一个action
    $route() {
        console.log(this.$route)
        // 路由组件名称(自定义) 过滤用 include 
        const componentName =this.$route.matched[0]["components"]["default"]["name"];
        // 路由组件path
        const detail = this.$route.path;
        // 当前路由需要显示到tab标签上名字,如 '直接入库'
        // const name = this.$route.meta[0]["name"];
        const name = this.$route.name;
        this.$store.dispatch("commitToolBar", { name, detail, componentName });
    }    
  }
};
</script>

<template>
  <div id="app">
     <CommonTools></CommonTools>
      <transition name="fade-transform" mode="out-in">     
        <keep-alive :include="cachePath">
          <router-view  />
        </keep-alive>
      </transition>
  </div>
</template>

<script>
import CommonTools from "@/components/commonTools.vue";
export default {
  name: "App",
  data() {
    return {
     
    };
  },
  components: {
   CommonTools
  },
  computed: {
    cachePath(el) {
      //上面cachePage里的名字要和相应页面export里的name一致
      return this.$store.state.cacheView;
    }
  },
  methods: {
    
  }
};
</script>

<style lang="scss">
</style>


// CSS  随意
.commonToolsWrap{
    width: 100%;
    // min-height: 64px;
    background: #FFFFFF;
    box-shadow: 0px 1px 4px 0px #E8E8E8;
    margin-bottom: 16px;
    padding-top:22px;
    position: relative;
    .commonTools{
        display: flex;
        align-items: flex-end;
        width: 90%;
        flex-flow: wrap;
        padding-left: 5px;
        .tabToolItem{
            position: relative;
            padding: 0px !important;
            margin-left: 8px;
            margin-top: 10px;
            display: flex;
            align-items: center;
            justify-content: flex-start;
            width: 180px;
            height: 40px;
            background: #FFFFFF;
            box-shadow: -1px 0px 0px 0px #E9EBEF, 1px 0px 0px 0px #E9EBEF, 0px 1px 0px 0px #E9EBEF;
            border-radius: 4px 4px 0px 0px;
            padding-left: 10px !important;
            cursor: pointer;
            .txt{
                font-size: 14px;
                font-family: PingFangSC-Regular, PingFang SC;
                font-weight: 400;
                color: #1D1F24;
                width: 140px;
                font-size: 14px;
                font-weight: 400;
                color: #1D1F24;
                overflow: hidden;
                text-overflow:ellipsis;
                white-space: nowrap;
            }
            .dot{
                position: absolute;
                content: '';
                top: 0px;
                left: 0px;
                width: 180px;
                height: 4px;
                background: #2D82FF;
                border-radius: 4px 4px 0px 0px;
            }
            .el-icon-close{
                width: 14px;
                height: 14px;
                margin-left: 8px;
            }
        }
   }
    .tabToolItem:first-child{
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值