Vue 其他页面跳转到 tab 页改变 tab 样式状态

一、问题描述

在移动应用中,大部分应用都是底部会有几个 tab 切换页。只是在底部切换到相应的页面,并且 tab 样式状态改变很容易实现,但是如果是其他页面跳转到 tab 页,tab 样式改变要如何实现昵?如下图,假设点击提交之后要调转到首页,并且修改首页 tab 样式为激活状态。
​​​​​​​​在这里插入图片描述

二、解决思路

  1. 以上三个 tab 切换组件必定有个公共组件,tab 样式的修改是在公共组件进行。
  2. 但是点击提交跳转是到首页,并且参数也是传到首页。
  3. 这时候就需要首页发个消息通知公共组件,并将参数带到公共组件,公共组件根据这个参数再去修改对应的 tab 样式。
  4. 子组件给父组件发通知用到的方法是 this.$emit()。
  5. 父组件接收通知是通过 v-on 指令。

三、代码示例

登陆页面 Login.vue

<template>
    <div class="contain">
    <div class="box-position">
        <div class="common-flex common-flex-jc-sb common-mt-10 common-mb-10">
            <label for="">用户名</label><input type="text" v-model="content">
        </div>
        <div>{{content}}</div>
        <div class="common-flex common-flex-jc-sb common-mt-10 common-mb-10">
            <label for="">密码</label><input type="text">
        </div>
        <div @click="getData" class="common-tx-c btn  mb">提交</div>
    </div>
    </div>
</template>
<script>
    import '../css/common.css';
    import axios from 'axios';
    export default{     
        methods: {
            getData(){
            this.$router.push({name:'index',params:{index:0}});
            }
        }
    }
</script>
<style>
    input{
        border-radius: 3px;
        height: 25px;
    }
    .contain{
        position: fixed;
        left: 0;
        right: 0;
        top: 0;
        bottom: 0;
        background: rgba(0,0,0,0.7);
    }
    .btn{
        border-radius: 5px;
        background: cornflowerblue;
        color: white;
        padding: 8px 10px;
        margin-top: 30px;
    }
    .box-position{
        position: fixed;
        left: 0;
        right: 0;
        transform: translateY(50%);
        border: 1px solid #ddd;
        border-radius: 10px;
        padding: 25px 20px;
        margin: 20px;
        background: white;
    }
</style>

说明:点击提交时通过 this.$router.push({name:‘index’,params:{index:0}});携参数 {index:0} 跳转到 Index 首页。

子组件Index.vue

<template>
    <div>
    <div v-for="item in list">
        {{item.text}}
    </div>
    </div>
</template>
<script>
    export default{
        data(){
            return {
                list:[
                    {text:'床前明月光'},
                    {text:'疑是地下霜'},
                    {text:'举头望明月'},
                    {text:'低头思故乡'},
                    ]
            }
        },
        created(){
            var index = this.$route.params && this.$route.params.index;
            this.$emit('changeIndex',index);
        }
    }
</script>

说明:首页通过 this. r o u t e . p a r a m s 获 取 参 数 , 并 通 过 t h i s . route.params 获取参数,并通过 this. route.paramsthis.emit 方法通知父组件,约定标识为 changeIndex, 同时带参数过去。

父组件App.vue

<template xmlns:v-bind="http://www.w3.org/1999/xhtml">
  <div id="app">    
      <div class="tab-position common-flex common-flex-jc-sa">
        <div v-for="(item,index) in tabList"
             @click="changeTab(item,index)"
             :class="[tabIndex == index ? activeTitle: activeTitleNo]"
        >
          {{item.title}}
        </div>
      </div>
    <router-view   v-on:changeIndex="change"></router-view>
  </div>
</template>
<script>
  import './css/common.css';
  let self;
  export default {
      data(){
          return{             
              tabList:[
                  {title:'首页',name:'index'},
                  {title:'论坛',name:'discussion'},
                  {title:'我的',name:'myInfo'}
              ],
              tabIndex:0,
              activeTitle:'active-title',
              activeTitleNo:'active-title-no',           
          }
      },
    created(){
        self = this;
    },
    methods:{
        changeTab:(item,index)=>{
              self.tabIndex = index;                   
              self.$router.push({name:item.name});
          },
        change:(data)=>{
            if(data && data.index || data && data.index ==0){              
                self.tabIndex = data.index;
            }
        }
    }
}
</script>
<style>
  .tab-position{
    position: fixed;
    bottom: 0;
    left: 0;
    right:0;
    z-index: 999;
  }
  .tab-title{
      background: darkred;
      text-align: center;
      padding: 8px;
      color: white;
  }
  .active-title{
    text-align: center;
    background: darkred;
    flex: 0.5;
    padding: 8px;
    color: white;
  }
  .active-title-no{
    text-align: center;
    background: #dddddd;
    flex: 0.5;
    padding: 8px;
    color: #333;
  }
</style>

说明:父组件通过 v-on:changeIndex=“change” ,将 change 方法赋值给约定的标识 changeIndex。在 change 方法中监控 data,如果有变化,就赋值给当前激活的 tab 。

Logo

前往低代码交流专区

更多推荐