使用vue 实现tabs 的总结
TIP
关于我为啥会实现一遍tabs组件呢?因为我们产品想在切换tabs的时候加入一些动画效果。那再参考Element UI 实现Tabs的一些总结 以及反思。
基础用法:
vue
<template>
<el-tabs v-model="activeName" @tab-click="handleClick">
<el-tab-pane label="用户管理" name="first">用户管理</el-tab-pane>
<el-tab-pane label="配置管理" name="second">配置管理</el-tab-pane>
<el-tab-pane label="角色管理" name="third">角色管理</el-tab-pane>
<el-tab-pane label="定时任务补偿" name="fourth">定时任务补偿</el-tab-pane>
</el-tabs>
</template>
<script>
export default {
data() {
return {
activeName: 'second'
};
},
methods: {
handleClick(tab, event) {
console.log(tab, event);
}
}
};
</script>
WARNING
<el-tabs/>
嵌套 <el-tab-pane/>
, 那咱们思考下 怎么做到使用activeName
做到控制那个tab页显示隐藏呢?怎么做到读取<el-tab-pane/>
的传值去绘制 tab页头呢?
读取全部<el-tab-pane/>
传参 做tab页表头
TIP
在<el-tabs/>
组件里面使用 this.$slots.default
获取全部组件做过滤,具体相关代码如下
vue
<!-- tabs.vue -->
<template>
<div class="tabs-container">
<tab-nav
:panes="tabPanes"
:current-name="currentName"
:on-tab-nav="onTabNav"
></tab-nav>
<div class="tab-body">
<slot></slot>
</div>
</div>
</template>
<script>
export default {
name: 'Tabs',
computed: {
tabPanes() {
if(this.$slots.default) {
// 使用 this.$slots.default or this.$children 都能获取到子组件数据信息
return this.$slots.default
.filter(vnode => vnode.tag &&
vnode.componentOptions &&
vnode.componentOptions.Ctor.options.name === 'ElTabPane');
}
return []
},
},
}
</script>
<el-tab-pane/>
怎么做到根据el-tabs v-model
显示隐藏的?
TIP
简单说下v-model
,在组件上使用v-model
数据双向绑定 实际是向组件传入了 :value='绑定的值'
, 组件需要更新数据使用this.$emit('input', 新数据)
,这么交互的。
那么在el-tabs组件中
vue
<!-- tabs.vue -->
<script>
export default {
props: {
value: { // v-model 数据
type: String,
required: true,
default: '',
},
},
}
</script>
在 el-tab-pane 组件中
vue
<!-- tab-pane.vue -->
<template>
<div
v-show="active"
v-if="((!lazy || loaded) || active)"
class="tab-pane__item"
>
<slot></slot>
</div>
</template>
<script>
export default {
name: 'TabPane',
props: {
label: {
type: String,
required: true,
default: '',
},
name: {
type: String,
required: true,
default: '',
},
lazy: {
type: Boolean,
required: false,
default: false,
},
},
data() {
return {
loaded: false,
};
},
computed: {
active() {
// 使用 this.$parent 获取 el-tabs 组件 v-model 绑定的value
const active = this.$parent.value === (this.name || this.index);
if (active) {
this.loaded = true;
}
return active;
},
},
}
</script>
动画设计参考
TIP
1、animate 一个特别好用的轻量级动画库
2、Effeckt.css 集成了各种组件炫酷动画
3、minimamente 各种炫酷交互式设计