文件夹xxtabs
四个文件 index暴露 render vue添加虚拟节点到插槽(自定义标签结构) tabs选项卡整体 abpaneq切换区
tabs.vue
<template>
<div class="gnip-tab">
<div class="gnip-tab-nav">
<div
v-for="(item, index) in tabNavList"
@click.stop="handleTabNavClick(item, index)"
:class="['tab-nav-item', item.name == activeName ? 'active' : '']"
ref="tabNavItemRefs"
>
<div class="tab_item" v-if="typeof item.label === 'string'">
{{ item.text }}
</div>
<render v-else :params="item.label"></render>
</div>
</div>
<!-- 滚动滑块 -->
<div class="tab-content-wrap">
<slot></slot>
</div>
</div>
</template>
<script>
// render组件,label为render函数的时候进行渲染
import Render from "./render";
export default {
props: {
// v-model的那项
value: {
type: String,
},
// 是否显示滑块背景
showTrackBg: {
type: Boolean,
default: false,
},
tabWidth: {
type: String,
default: "",
},
},
components: {
Render,
},
data() {
return {
// tab数组
tabNavList: [],
// 当前活跃项
activeName: "",
// 滑块的宽度
trackLineWidht: 0,
// 当前活跃索引
currentIndex: 0,
// 滑块偏移量
left: 0,
// 拖拽开始的哪项
dragOriginItemIndex: null,
// 拖拽活跃项的索引
dragStartIndex: null,
};
},
mounted() {
this.init();
},
methods: {
// 初始化
init() {
// 默认当前活跃项为外部v-model的值
this.activeName = this.value;
},
// 设置tab点击栏
setTabBar(tabsPaneInstance, slotElement) {
// tab的描述信息可以是字符串也可以是render函数
const label = tabsPaneInstance.label,
type = typeof label;
// 添加到数组项中,根据添加条件渲染
this.tabNavList.push({
text: type == "function" ? "" : label,
renderFun: type == "function" ? label : "",
name: tabsPaneInstance.name,
label: slotElement.tab === undefined ? label : slotElement.tab,
});
},
handleTabNavClick(item, index) {
console.log('name',item,index)
if (item.name == this.activeName) return;
// 更新当前活跃项
this.activeName = item.name;
// 活跃项的索引
this.currentIndex = index;
},
// 交换tab数据项
swap(start, end) {
let startItem = this.tabNavList[start];
let endItem = this.tabNavList[end];
// 由于直接通过索引修改数组,无法触发响应式,因此需要$set
this.$set(this.tabNavList, start, endItem);
this.$set(this.tabNavList, end, startItem);
},
},
};
</script>
<style scoped>
.gnip-tab {
height: 100%;
/* width: var(tabWidth); */
/* width: 200px; */
}
.gnip-tab-nav {
display: flex;
position: relative;
}
.tab-nav-item {
background-color: #074889;
padding-left: 5px;
padding-right: 5px;
line-height: 18px;
text-align: center;
height: 24px;
box-sizing: border-box;
background: rgb(7, 72, 137);
border-left: 1px solid rgb(44, 100, 155);
border-right: 1px solid rgb(44, 100, 155);
border-bottom: 1px solid rgb(44, 100, 155);
border-radius: 0px 0px 5px 5px;
}
.tab-nav-item.active {
background-color: #0078ef;
}
.tab-nav-track {
width: 100%;
position: relative;
height: 2px;
}
.tab-content-wrap{
height: calc(100% - 24px);
}
.track-line {
height: 2px;
background-color: #2d8cf0;
position: absolute;
transition: left 0.35s;
}
.tab_item {
}
</style>
tabPane.vue
<template>
<div class="gnip-tabs-pane" v-if="$parent.activeName === name">
<!-- <transition :name="paneTransitionName"> -->
<div class="tab-pane-content" >
<slot name="default"></slot>
<!-- <slot name="one"></slot> -->
</div>
<!-- </transition> -->
</div>
</template>
<script>
export default {
props: {
label: {
type: [String, Function],
},
name: {
type: String,
},
disabled: {
type: Boolean,
default: false,
},
},
data() {
return {
paneTransitionName: "enter-right",
};
},
created() {
this.$parent.setTabBar(this,this.$slots);
},
mounted(){
},
};
</script>
<style scoped>
.gnip-tabs-pane {
height: 100%;
overflow-x: hidden;
}
.tab-pane-content{
height: inherit;
}
</style>
render.js
import { h } from 'vue'
export default {
data() {
return {
msg: 'hello'
}
},
props:{
params: {
type: Function,
default() {
return function(){};
},
},
},
render() {
//获取插槽内容创建成div
return h('div', this.params())
}
}
index.js
import TabPane from "./TabPane.vue";
import Tabs from "./Tabs.vue";
export { Tabs, TabPane };
使用
引入
import { Tabs, TabPane } from "@/components/SreenTabs";
使用
<Tabs style="margin-left: 10px" :value="logTabName" show-track-bg>
<TabPane label="日志" name="日志">
日志文本
</TabPane>
<TabPane label="消息" name="消息">
<template v-slot:tab>
<n-badge :value="8" :offset="[5, -2]">
<text style="color: white">消息</text></n-badge
>
</template>
消息文本
</TabPane>
<TabPane label="异常" name="异常">
异常文本
</TabPane>
</Tabs>