vue中做Tab标签页(路由守卫)

前言:需要做的效果如下图:

用到的技术栈:vue、vuex、vue-router。主要的vue-router的路由守卫。

 

一、首先,看一下vue-router的路由守卫

注意:这三个方法是依次调用的(有点类似于生命周期有执行顺序一样)

           路由守卫在刚进入页面时,是不会执行的

           回调函数中的三个参数:

           

二、代码实现

1. 新建 tagView.js 保存显示的Tab标签的路由信息  ==> 实现三个方法,新增、删除和清空

export default {
    namespaced: true,
    state: {
        allVisitedTags: [ ],
    },
    mutations: {
        // 添加一个tab标签
        addVisitedTags (state, newData) {
            const newArr = state.allVisitedTags;
            const item_index = newArr.findIndex(e => e.path == newData.path);

            if(item_index == -1){           //如果没有,直接添加
                if(newArr.length <= 10){        //如果在10条tab之内,直接添加
                    newArr.push(newData);            
                    state.allVisitedTags = newArr;
                }
                else{       //如果大于10条tab,则删除前面的,然后再添加
                    newArr.splice(0, 1); 
                    newArr.push(newData);            
                    state.allVisitedTags = newArr;
                }                
            }else{              //如果有,则替换
                newArr.splice(item_index, 1, newData); 
            }
        },
        // 删除一个tab标签
        delVisitedTags (state, newData) {
            const newArr = state.allVisitedTags;
            const item_index = newArr.findIndex(e => e.path == newData.path);
            newArr.splice(item_index, 1);
            
            state.allVisitedTags = newArr;
        },
        // 清空所有tab标签
        clearVisitedTags (state, newData) {
            const newArr = [];
            
            state.allVisitedTags = newArr;
        },
    }
  }
  

2. 将 tagView 引入并放到vuex中

3. 在App.vue 或者 main.vue中(看自己项目而定,主要是放在一个全局的位置)

created() {      
      
      // 刚进来的页面
      this.dealRoute(this.$route)

      // 路由守卫,每次跳转页面时
      this.$router.beforeEach((to, from, next) => {
        //有menuId,表示为一级菜单,即直接配置的菜单,切换时需要清空tab标签   并且点击的不是当前页面的一级菜单
        if(to.meta.menuId && to.meta.menuId !== this.allTagsArr[0].meta.menuId){
          this.$store.commit('tagView/clearVisitedTags') 
          this.dealRoute(to)
        }else{    //没有menuId,表示为二级有了
          this.dealRoute(to)
        }
        
        next();
      });

},

3.1 dealRoute 函数的实现

 dealRoute(itemObj){
        const cutOutIndex = itemObj.path.indexOf("{");          //正常进入是一个字符串的 {  ==> 不是对象的情况不用管
        const cutOutIndex_02 = itemObj.path.indexOf("%");       //再一次进入就变成了转义字符 ==> 不是对象的情况不用管         
        const index_finally = cutOutIndex > cutOutIndex_02 ? cutOutIndex : cutOutIndex_02;          //肯定只有一种情况满足,另一个肯定找不到(取找得到的那个即可)

        const routePath = index_finally == -1 ? itemObj.path : itemObj.path.substring(0,index_finally-1)
        // itemObj.path = routePath;       //把路由信息的path字段改一下(不带参数)

        const routerObj = {
          // path: itemObj.path,
          path: routePath,
          params: itemObj.params,
          query: itemObj.query,
          meta: itemObj.meta,
          name: itemObj.name
        }
        this.$store.commit('tagView/addVisitedTags', routerObj) 
        // this.currentTagView = this.allTagsArr.findIndex(e => e.path == itemObj.path)
        this.currentTagView = this.allTagsArr.findIndex(e => e.path == routePath)
},

3.2 allTagsArr 所有Tab页的数组是从vuex中获取的,写在computed中

allTagsArr: {
    get() { return this.$store.state.tagView.allVisitedTags }
},

3.2 currentTagView表示当前在哪个Tab页,默认为0

 data() {
    return {        
        currentTagView: 0,    //当前在哪一个标签
    }
},

3.4 页面实现

 <div class="tagViewBox">
      <p v-for="(item,index) in allTagsArr" @click="skipTagView(item)" :class="{ active: currentTagView == index }">
           <span :title='item.meta.title'>{{item.meta.title}}</span>
           <i class="el-icon-close" @click.stop="delTag(item)"></i>
      </p>
</div>



//样式如下(仅做参考哦)
.tagViewBox{
  display: flex;
  padding: 10px 20px;
  & > p{
    margin: 0;
    padding: 8px 10px;
    border: solid 1px #B777C0;
    border-left: none;
    color: #ccc;
    cursor: pointer;
    max-width: 9%;
    display: flex;
    & > span:nth-child(1){
      display: block;
      width: 90%;
      margin-right: 5px;
      overflow: hidden;
      text-overflow:ellipsis;
      white-space: nowrap;
    }
  }
  & > p:nth-child(1){
    border-left: solid 1px #B777C0;
  }
  & > p.active{
    color: #B777C0;
    border-bottom: none;
  }
}

3.5 删除一个Tab标签  ===>> delTag方法

delTag(item){     //删除一个标签页
        if(this.allTagsArr.length >= 2){
          this.$store.commit('tagView/delVisitedTags', item) 
          this.currentTagView--;    //删除一个tab后,将当前tab页设置成前一个
          this.skipTagView(this.allTagsArr[this.currentTagView]);     //跳转到前一个tab页面内容
        }else{
          this.$message({
            message: '这是当前最后一个Tab页,请在侧边栏切换模块。',
            type: 'warning'
          });
        }
      },

3.6 跳转到指定标签页 ===>> skipTagView方法

skipTagView(item){           //跳转到一个标签页
        if(JSON.stringify(item.params) != '{}'){      //把以前的参数传过去,为了不去拼接path,直接使用name修改路由
          this.$router.push({ name: item.name, params: item.params })
        }
        else if(JSON.stringify(item.query) != '{}'){
          this.$router.push({ name: item.name, query: item.query })
        }
        else{
          this.$router.push(item.path)
        }
      }

 

三、总结

1. 在跳转到指定标签页的时候,用 {name: ' ', params/query: ' ' } 方式,可以避免拼接路由的path

2. 在路由参数是 Object 时,只能传字符串,但是其第一次是正确的,第二次就被浏览器用 UrlEncode编码/解码 (可在线解码)方式转义了,所以在截取路由的时候要判断两种情况

      第一次:

      第二次:

 

文章仅为本人学习过程的一个记录,仅供参考,如有问题,欢迎指出!

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
如果你使用了vue-router进行路由跳转,但是tab标签没有跟着跳转,可能是因为你没有为tab标签设置相应的路由。 一种解决方法是,为每个标签设置一个对应的路由,然后在路由跳转时,同时更新选标签。例如: ```javascript // 在路由配置设置每个标签对应的路由 const routes = [ { path: '/home', component: Home, meta: { tab: 'home' } }, { path: '/about', component: About, meta: { tab: 'about' } }, { path: '/contact', component: Contact, meta: { tab: 'contact' } } ]; // 在使用<router-view>来显示当前路由对应的组件 <template> <div> <div class="tabs"> <div :class="{ active: activeTab === 'home' }" @click="selectTab('home')">Home</div> <div :class="{ active: activeTab === 'about' }" @click="selectTab('about')">About</div> <div :class="{ active: activeTab === 'contact' }" @click="selectTab('contact')">Contact</div> </div> <router-view></router-view> </div> </template> <script> export default { data() { return { activeTab: 'home' }; }, methods: { selectTab(tab) { // 更新选标签 this.activeTab = tab; // 跳转到对应的路由 this.$router.push({ path: '/' + tab }); } }, watch: { // 监听路由变化,更新选标签 $route(to) { this.activeTab = to.meta.tab; } } }; </script> ``` 这样,在跳转路由时,标签也会跟着更新。如果你使用的是其他的标签组件库,也可以根据类似的原理进行修改。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值