Vue 组件封装之 TabBottom 底部导航

一、TabBottom 组件

组件说明:
实现底部 tab 切换。

效果展示:
底部 tab 切换,改变激活样式,切换到对应的页面
在这里插入图片描述

二、使用案例

说明:分别在【我的】、【添加】以及【团队】页面引用 el-tab-bottom 组件。
提示:可以将公共的 tabList 放在 store 中。

【我的】页面引用el-tab-bottom

<template>
 <div>这是我的页面</div>
 <el-tab-bottom :tabList="tabList" :defaultTab="0" @on-click="changeTabBottom"/>
</template>
<script>
 export default{
    data(){
      return{
        tabList:[
          {title:'我的',path:'my',icon:my,checkedIcon:myCheck},
          {title:'添加',path:'',icon:add,checkedIcon:addCheck},
          {title:'团队',path:'myTeam',icon:myTeam,checkedIcon:myTeamChecked}
        ],
       }
    },
    methods:{
       changeTabBottom(item,index){},
    }
}
</script>

【添加】页面引用el-tab-bottom

<template>
 <div>这是添加页面</div>
 <el-tab-bottom :tabList="tabList" :defaultTab="1" @on-click="changeTabBottom"/>
</template>
<script>
 export default{
    data(){
      return{
        tabList:[
          {title:'我的',path:'my',icon:my,checkedIcon:myCheck},
          {title:'添加',path:'',icon:add,checkedIcon:addCheck},
          {title:'团队',path:'myTeam',icon:myTeam,checkedIcon:myTeamChecked}
        ],
       }
    },
    methods:{
       changeTabBottom(item,index){},
    }
}
</script>

【团队】页面引用el-tab-bottom

<template>
 <div>这是团队页面</div>
 <el-tab-bottom :tabList="tabList" :defaultTab="2" @on-click="changeTabBottom"/>
</template>
<script>
 export default{
    data(){
      return{
        tabList:[
          {title:'我的',path:'my',icon:my,checkedIcon:myCheck},
          {title:'添加',path:'',icon:add,checkedIcon:addCheck},
          {title:'团队',path:'myTeam',icon:myTeam,checkedIcon:myTeamChecked}
        ],
       }
    },
    methods:{
       changeTabBottom(item,index){},
    }
}
</script>

三、API 使用指南

属性说明类型默认值
tabList数组,将底部的tab名称,路由等信息组合到tabListArray[]
on-clicktab 被选中时触发点击按钮的回调函数(e: Object): void
defaultTab默认选中的tabNumber0

tabList 属性

属性说明类型默认值
title底部的tab文字string“”
path点击tab之后跳转到对应的页面路径名称string“”
icon未选中时的图标string“”
checkedIcon选中时的图标string“”

四、源代码

TabBottom.vue

<template>
    <div class="tab-fill-height">
      <div class="tab-position-fixed">
        <div v-for="(item,index) in tabList"
             @click="changeTab(item,index)"
             :class="activeTab == index ? 'tab-title-active': 'tab-title'"
        >
          <img :src="activeTab == index ? item.checkedIcon:item.icon" alt="" class="tab-icon-20">
          <div class="tab-text">{{item.title}}</div>
        </div>
      </div>
    </div>
</template>
<script>
  export default {
    name: "ElTabBottom",
    data(){
      return{
        activeTab:0
      }
    },
    created(){
      this.activeTab = this.defaultTab;
    },
     //获取子组件传过来的激活tab
    props:{
      tabList:{
        type: Array,
        default: function () {
          return [];
        }
      },
      defaultTab:{
        type:Number,
        default:0
      }
    },
    methods:{
      changeTab(item,index){   
      //如果传了路由路径就是跳转页面,没传路径就交给父组件处理,比如  点击某个tab弹框而不是跳转页面。
          if(item.path){
            this.activeTab = index;//改变选中的底部tab样式    
            this.$router.push({name:item.path});//跳转对应的路由页面
          };      
         this.$emit('on-click',item,index);//将点击Tab的事件暴露给父组件
      }
    }
  }
</script>
<style>
  //填充由fixed定位造成的数据流脱离高度
  .tab-fill-height{
    width: 100%;
    height: 50px;
  }
  /*兼容iphoneXR底部遮住小黑条*/
  @supports (bottom: env(safe-area-inset-bottom)){
    .tab-position{
      padding-bottom: calc(-50px + env(safe-area-inset-bottom));
      }
  }
  //绝对定位
  .tab-position-fixed{
    position: fixed;
    bottom: 0;
    left: 0;
    right:0;
    height: 50px;
    z-index: 999;
    display: flex;
    align-items: center;
    justify-content: space-around;
    background: #fff;
    border-top: 1px solid #ddd;
  }
  //默认或者选中的tab样式
  .tab-title-active{
    color: #005398;
    display: flex;
    flex-direction: column;
    align-items: center;
  }
   //未选中的tab样式
  .tab-title{
    color: #999;
    display: flex;
    flex-direction: column;
    align-items: center;
  }
  //底部文字样式
  .tab-text{
   margin-top:3px;
   font-size:12px
  }
  //底部图标大小
  .tab-icon-20{
    width: 20px;
    height: 20px;
  }
</style>
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Vue3 的组件封装非常简单,下面是一个搜索组件封装示例: 首先,创建一个 Search.vue组件,它的模板如下: ```html <template> <div class="search"> <input type="text" v-model="searchInput" @input="handleInput" /> <button @click="handleSearch">搜索</button> </div> </template> ``` 在组件中,我们需要引入 `reactive`,这是 Vue3 中新加入的函数,用于将数据转换为响应式的数据。我们还需要定义 `props`,用于接收父组件传递的参数,以及定义 `emit`,用于向父组件发送事件。 ```javascript import { defineComponent, reactive, emit } from 'vue'; export default defineComponent({ name: 'Search', props: { placeholder: { type: String, default: '请输入关键词', }, }, setup(props, { emit }) { const searchInput = reactive({ value: '', }); const handleInput = (event) => { searchInput.value = event.target.value; }; const handleSearch = () => { emit('search', searchInput.value); }; return { searchInput, handleInput, handleSearch, }; }, }); ``` 在 `setup` 函数中,我们使用 `reactive` 将 `searchInput` 对象转换为响应式数据。当用户输入关键词时,`handleInput` 函数被调用,将输入的值赋值给 `searchInput.value`。当用户点击搜索按钮时,`handleSearch` 函数被调用,向父组件发送 `search` 事件,并将输入框的值作为参数传递给父组件。 最后,在父组件中使用该组件: ```html <template> <div> <Search placeholder="请输入关键词" @search="handleSearch" /> <ul> <li v-for="item in searchResult" :key="item.id">{{ item.name }}</li> </ul> </div> </template> <script> import Search from './Search.vue'; export default { components: { Search, }, data() { return { searchResult: [], }; }, methods: { handleSearch(keywords) { // 这里实现搜索逻辑,将搜索结果赋值给 searchResult this.searchResult = [ { id: 1, name: '搜索结果1' }, { id: 2, name: '搜索结果2' }, { id: 3, name: '搜索结果3' }, ]; }, }, }; </script> ``` 在父组件中,我们通过 `@search` 监听子组件的 `search` 事件,并在 `handleSearch` 方法中实现搜索逻辑。将搜索结果赋值给 `searchResult`,然后通过 `v-for` 渲染出结果列表。 这就是 Vue3 中搜索组件封装方法,简单易用。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值