Vue 组件封装之 tab 切换

  • 一、Tab 切换组件
  • 二、使用案例
  • 三、API 使用指南
  • 四、源代码
  • 五、总结

一、Tab 切换组件

组件说明:
实现 tab 切换。

效果展示:
实现 tab 切换,改变激活样式,切换到对应的页面

以上 tab 切换功能在前端开发中司空见惯。各种现存的组件也随手拈来。在 Vue 中,有配套的 element-ui 组件,也有 vue-ant-design。

element-ui 中 el-tabs 效果如下:

vue-ant-design 中 a-tabs 效果如下:

但是使用现存组件面临的问题如下

  1. element-ui 中 el-tabs 使用问题
    tab 标签文本没有居中,整体靠左,通过复写样式也不行,因为下面的高亮下划线是通过 JS 动态控制。
  2. vue-ant-design 中 a-tabs 使用问题
    tab 标签文本间的距离太大。
  • 基于以上问题,所以打算自己封装一个 tab 组件。

二、使用案例

该组件有两种使用方式。

  1. 只有一个主页面,切换时更新数据源即可,用法如下。
<template><el-tab defaultKey="1" @on-click="changeTab"><el-tab-panes actKey="1" label="全部"></el-tab-panes><el-tab-panes actKey="2" label="推荐"></el-tab-panes><el-tab-panes actKey="3" label="最新"></el-tab-panes></el-tab><div>只有我一个页面,更新数据源即可</div>
</template>
<script>export default{data(){return{}},methods:{changeTab(item,index){//调数据}}
}
</script>
  1. 有几个tab,就有几个主页面,切换时切换到不同的页面,用法如下。
<template><el-tab defaultKey="1" @on-click="changeTab"><el-tab-panes actKey="1" label="全部"><div>页面1</div></el-tab-panes><el-tab-panes actKey="2" label="推荐"><div>页面2</div></el-tab-panes><el-tab-panes actKey="3" label="最新"><div>页面3</div></el-tab-panes></el-tab>
</template>
<script>export default{data(){return{}},methods:{changeTab(item,index){//调数据}}
}
</script>

三、API 使用指南

属性 说明 类型 默认值
defaultKey 默认选中的tab String 1
actKey 每个tab的唯一key String
label 每个tab的标题 String
on-click tab 被选中时触发 点击按钮的回调函数 (e: Object): void

四、源代码

实现思路
(1) tab 标签文本样式高亮;
(2) tab 下面的下划线调整到相应位置;
(3) tab 对应的内容切换。

  1. tabs 组件
<template><div><div class="tabs"><div  ref="line" class="tab-line"></div><div :class="[activeKey == item.actKey? 'active-tab' : 'tab']"  @click="changeTab($event,item,index)" v-for="(item,index) in childList">{{item.label}}</div></div><slot></slot></div>
</template>
<script>let self;export default {name: "ElTab",data(){return {childList:[],activeKey:this.defaultKey,//将初始化tab赋值给activeKeyslideWidth:0}},//获取子组件传过来的激活tabprops:{defaultKey:{type: String,default: "1"}},created(){self = this;},mounted(){//循环tab标签this.childList = this.$children;//设置滑动距离。平分设备宽度this.slideWidth = window.innerWidth/this.childList.length;//设置状态线初始化滑动位置this.$refs.line.style.width = this.slideWidth+"px";},methods:{//切换tab触发事件changeTab:(event,item,index)=>{self.activeKey = item.actKey;self.$refs.line.style.transform = "translateX("+self.slideWidth*index+"px)";self.$refs.line.style.transition = "transform .3s";self.$emit('on-click',item,index);//将切换tab的事件暴露给父组件},//初始化时tab状态设置与相应内容显示updateNav:()=>{self.$children.map((item,index)=>{if(item.actKey == self.activeKey){item.show = true;self.$nextTick(function() {self.$refs.line.style.transform = "translateX("+self.slideWidth*index+"px)";self.$refs.line.style.transition = "transform 0s";});}else {item.show = false;}})}},watch: {//监听当前tab,显示相应内容activeKey() {self.$children.map((item)=>{if(item.actKey == self.activeKey){item.show = true;}else {item.show = false;}})}}}
</script>
<style>.active-tab{color:#158ef3;height: 50px;font-weight: bold;line-height: 50px;font-size: 16px;}.tab{color:#333;height: 50px;line-height: 50px;font-size: 16px;}.tabs{display: flex;justify-content: space-around;align-items: center;height: 50px;border-bottom: 1px solid #f6f6f6;}.tab-line{position: absolute;left: 0;border-bottom: 2px solid #158ef3;height: 50px;}
</style>
  1. tab-pane 组件
<template><div v-if="show"><slot></slot></div>
</template>
<script>export default {name: "ElTabPanes",data(){return {show: false //初始时将所有内容隐藏}},props:{actKey:{type: String,default: "1"}, label:{type: String,default: ""},},mounted(){this.$parent.updateNav();},}
</script>

五、总结

最后总结一下封装一个 tabs 的核心思路和方法。

1. 设置初始化 tab 标签

在 tab-pane 子组件中将所有的内容隐藏(show 属性设置为 false),在 tabs 父组件内接收由开发者自定义的 activeKey,定义一个方法,将 activeKey与子组件的 actKey 比较,如果相同,则该 tab 为初始化时激活的 tab 标签,将相应 tab 的 show 属性设置为 true,并修改 tab 样式。该方法在 tab-pane 子组件中调用。

将 tab-pane 子组件中所有的开发者添加的内容隐藏:

tabs 父组件提供的方法:

tab-pane 子组件调用:

  1. tabs 组件内部循环 tab-pane 子组件的标签。接收 activeKey,点击时将 tab-pane 子组件的 actKey 赋值给 activeKey。然后每个 tab 的样式通过当前 activeKey 与 actKey 比较,判断是否是当前 tab 标签。如果是,则样式设置为激活样式。
<div :class="[activeKey == item.actKey? 'active-tab' : 'tab']"  @click="changeTab($event,item.actKey,index)" v-for="(item,index) in childList">{{item.label}}</div>changeTab:(event,tab,index)=>{self.activeKey = tab;self.$refs.line.style.transform = "translateX("+self.slideWidth*index+"px)";self.$refs.line.style.transition = "transform .3s";self.$emit('on-click',event,tab)},
  1. 在 tab-pane 上方添加状态线,状态线的样式需要注意一下。
<div  ref="line" class="tab-line"></div>.tab-line{height: 2px;background: #409eff;position: absolute;left: 0;margin-top: 20px;}
  1. 切换 tab 时,改变相应的内容。
    这一步最关键,需要在 tabs 组件中使用 watch 监听当前状态,如果子组件中的 actKey 等于当前状态,则显示相应的内容。
     activeKey() {self.$children.map((item)=>{if(item.actKey == self.activeKey){item.show = true;}else {item.show = false;}})}

Vue 组件封装之 Tab 切换相关推荐

  1. 本篇文章使用vue结合element-ui开发tab切换vue的不同组件,每一个tab切换的都是一个新的组件。

    本篇文章使用vue结合element-ui开发tab切换vue的不同组件,每一个tab切换的都是一个新的组件. 1.vue如何使用element-ui 上一篇文章已经分享了如何在vue中使用eleme ...

  2. Vue组件封装,(面试回答)

    在我用vue开发项目的时候,一般我都会用到组件封装,采用组件化的思想进行项目开发,我在搭建一个项目的时候,就会创建一个views目录和一个commen目录和一个feature目录,views目录中放页 ...

  3. Vue组件封装 (面试必问)

    先说一下vue组件封装的优点 组件(Component)是Vue.js最强大的功能之一 组件可以扩展HTML元素, 封装可重用代码 组件是可复用的Vue 实例 组件可以提升整个项目的开发效率.能够把页 ...

  4. vue组件封装技巧,如何对vue模块进行功能封装

    如何对vue模块进行功能封装,vue组件封装技巧 当业务不断累加,导致原本干净整洁的代码越来越冗余,各种变量和注释已经让他人望而却步,往往又苦于重构带来的成本,导致诞生很多巨石应用.与其让自己或他人面 ...

  5. Vue 组件封装之 ScrollView 上拉加载更多

    Vue 组件封装之 ScrollView 上拉加载更多 一.ScrollView 上拉加载更多 二.使用案例 三.API 使用指南 四.源代码 一.ScrollView 上拉加载更多 组件说明: 实现 ...

  6. Vue 组件封装之 Questionnaire 问卷调查

    Vue 组件封装之 Questionnaire 问卷调查 前言 一.Questionnaire 组件 二.使用案例 三.API 使用指南 四.源代码 前言 问卷调查表也是目前前端比较常见的开发项目,目 ...

  7. Vue 组件封装之 Content 列表(处理多行输入框 textarea)

    Vue 组件封装之 Content 列表 一.Content 列表 二.使用案例 三.API 使用指南 四.源代码 一.Content 列表 组件说明: 实现 Content 列表布局排版. 效果展示 ...

  8. Vue 组件封装之 List 列表

    Vue 组件封装之 List 列表 一.List 列表 二.使用案例 三.API 使用指南 四.源代码 一.List 列表 组件说明: 实现 List 列表布局排版. 效果展示: 实现的功能: 在一个 ...

  9. Vue 组件封装之 Search 搜索

    Vue 组件封装之 Search 搜索 一.Search 组件 二.使用案例 三.API 使用指南 四.源代码 一.Search 组件 组件说明: 实现搜索功能. 效果展示: input 输入框背景铺 ...

最新文章

  1. 谈一谈我对AI项目落地的看法
  2. TensorFlow的基础概念03
  3. java book打印机_Java调用打印机进行打印
  4. SQLserver分页 高效率
  5. 使用sortable插件实现列表中表项的拖曳排序操作8-3
  6. 奥巴马经济顾问:哪怕丢了“饭碗”,也必须加大投资AI!
  7. python仿真智能驾驶_基于Python的3R机器人运动仿真
  8. 《走遍中国》珍藏版(九)
  9. Java 8日期时间API教程:LocalDateTime
  10. Android开发日记(六)
  11. 在线编辑ewebeditor
  12. Foxmail配置IMAP账号
  13. 【影视APP】分享一个影视APP源码
  14. WIN11映射NAS网络驱动器提示 用户名和密码错误
  15. SAP跨公司销售经典场景
  16. opencv 打开摄像头
  17. KMP(字符串匹配)+字符串哈希
  18. 关于数据恢复,记一次修复SD卡 RAW 之后的修复过程
  19. 数据结构基本英语词汇
  20. 视频通话和直播技术webRTC和RTMP探究

热门文章

  1. 实战交叉编译——Ubuntu下交叉编译MiniDLNA到DD-WRT
  2. 实践分享:一定要用OKR进行持续绩效管理的4个理由
  3. 解决 .webp 格式图片在 ios 设备上无法正常显示的问题
  4. tomcat高级操作
  5. Centos 7 安装MySQL5.7.35,顺便练习一下数据库基本操作
  6. mac读取pc硬盘_如何在Windows PC上读取Mac格式化的驱动器
  7. ABB DSQC652 I/O板通讯端子接线图
  8. 光盘刻录系列之假重写之文件名检测冲突
  9. fanuc机器人I/O分配
  10. 音速战绩查询器v1.04