在业务中,可能会遇到需要对多tab的交互或UI做全新设计的需求,这个时候可以自定义多tab组件支持。
首先继承平台的MultiTabsWidget组件,将自己vue文件设置到component处
import { MultiTabsWidget, SPI, ViewWidget } from '@kunlun/dependencies';
import Component from './CustomMultiTabs.vue';
@SPI.ClassFactory(
ViewWidget.Token({
// 这里的tagName跟平台的组件一样,这样才能覆盖平台的组件
tagName: ['multi-tabs', 'MultiTabs']
})
)
export class CustomMultiTabsWidget extends MultiTabsWidget{
public initialize(props) {
super.initialize(props);
// 设置自定义的vue组件
this.setComponent(Component);
return this;
}
}
vue文件中继承平台的props,编写自定义页面代码
export const MultiTabsProps = {
/**
* 组件是否可见
*/
invisible: {
type: Boolean
},
/**
* tab列表数据
*/
tabs: {
type: Array as PropType<MultiTab[]>
},
/**
* 当前激活的tab
*/
activeTab: {
type: Object as PropType<MultiTab>
},
/**
* 鼠标悬浮所在的tab
*/
hoverTab: {
type: Object as PropType<MultiTab>
},
/**
* 鼠标经过tab事件回调
*/
onMouseenterTab: {
type: Function as PropType<(tab: MultiTab) => void>
},
/**
* 鼠标离开tab事件回调
*/
onMouseleaveTab: {
type: Function as PropType<(tab: MultiTab) => void>
},
/**
* 点击tab
*/
onClickTab: {
type: Function as PropType<(tab: MultiTab) => void>
},
/**
* 刷新当前tab
*/
onRefreshCurrentTab: {
type: Function as PropType<(tab: MultiTab) => void>
},
/**
* 关闭当前tab
*/
onCloseCurrentTab: {
type: Function as PropType<(tab: MultiTab) => void>
},
/**
* 关闭除当前tab外的其他所有tab
*/
onCloseOtherTabs: {
type: Function as PropType<(tab: MultiTab) => void>
},
/**
* 关闭当前tab左侧的所有tab
*/
onCloseLeftTabs: {
type: Function as PropType<(tab: MultiTab) => void>
},
/**
* 关闭当前tab右侧的所有tab
*/
onCloseRightTabs: {
type: Function as PropType<(tab: MultiTab) => void>
},
/**
* 新窗口打开当前tab
*/
onOpenCurrentTabOnNewWindow: {
type: Function as PropType<(tab: MultiTab) => void>
}
};
<template>
<div class="k-layout-multi-tabs-main-area" v-if="tabs && tabs.length && !invisible">
<div id="k-layout-multi-tabs" class="k-layout-multi-tabs oio-scrollbar">
<div
v-for="(tab, index) in tabs"
:key="tab.key"
:id="`k-layout-multi-tabs-tab-${index}`"
class="k-layout-multi-tabs-tab"
:class="{
'k-layout-multi-tabs-tab-active': activeTab && tab.key === activeTab.key,
'active-left-hover': activeTabLeftHoverTab,
'k-layout-multi-tabs-tab-closable': allowClosable
}"
@click="onClickTab(tab)"
@mouseenter="onMouseenterTab(tab)"
@mouseleave="onMouseleaveTab(tab)"
>
<div class="first-tab-icon" v-if="index === 0">
<oio-icon icon="oinone-shouye1" />
</div>
<div class="k-layout-multi-tabs-tab-title" :title="tab.title">{{ tab.title }}</div>
<div class="close-button-area" :class="[index === 0 && 'k-layout-multi-tabs-tab-close-btn']">
<oio-button type="link" @click.stop.prevent="onCloseCurrentTab">
<oio-icon icon="oinone-guanbi" size="16px" />
</oio-button>
</div>
<div class="split-area" v-if="!isInvisibleSplit(index)"></div>
</div>
</div>
<div class="k-layout-multi-tabs-tools">
<oio-dropdown trigger="click" overlay-class-name="top-bar-common-dropdown">
<oio-icon icon="oinone-xiala2" size="16px" />
<template #overlay>
<div class="multi-tab-tool-overlay">
<span
v-for="item in TabToolItems"
:key="item.key"
:class="['multi-tab-tool-overlay-item', isTabToolItemDisable(item) && 'disabled']"
@click="onTabToolItemClick(item)"
>
{{ item.title }}
</span>
</div>
</template>
</oio-dropdown>
</div>
</div>
</template>
<script lang="ts">
import { computed, defineComponent, watch } from 'vue';
import { MultiTabsProps, OioIcon, TabToolItems } from '@kunlun/dependencies';
import { OioButton, OioDropdown } from '@kunlun/vue-ui-antd';
export default defineComponent({
name: 'MyMultiTabs',
inheritAttrs: false,
components: { OioButton, OioDropdown, OioIcon },
props: {
...MultiTabsProps
},
setup(props) {
const activeTabLeftHoverTab = computed(() => {
return (
props.activeTab &&
props.hoverTab &&
props.activeTab.currentIndex !== undefined &&
props.hoverTab.currentIndex !== undefined &&
props.activeTab.currentIndex + 1 === props.hoverTab.currentIndex
);
});
watch(
() => props.activeTab,
() => {
setTimeout(() => {
if (props.activeTab && props.activeTab.currentIndex) {
const tabDoc = document.getElementById(`k-layout-multi-tabs-tab-${props.activeTab.currentIndex}`);
if (tabDoc) {
tabDoc.scrollIntoView(false);
}
}
}, 10);
}
);
const allowClosable = computed(() => (props.tabs?.length || 0) >= 2);
function isInvisibleSplit(index: number) {
if (
props.hoverTab &&
props.hoverTab.currentIndex !== undefined &&
(props.hoverTab.currentIndex === index || props.hoverTab.currentIndex - 1 === index)
) {
return true;
}
if (props.activeTab && props.activeTab.currentIndex !== undefined && props.activeTab.currentIndex >= 0) {
return props.activeTab.currentIndex === index || props.activeTab.currentIndex - 1 === index;
}
return false;
}
function isTabToolItemDisable(tabToolItem) {
return tabToolItem.disabled(props.tabs?.length || 0, props.activeTab ? props.activeTab.currentIndex : -1);
}
function onTabToolItemClick(tabToolItem) {
if (isTabToolItemDisable(tabToolItem)) {
return null;
}
props.activeTab && props[tabToolItem.key]?.(props.activeTab);
}
return {
activeTabLeftHoverTab,
allowClosable,
TabToolItems,
isInvisibleSplit,
isTabToolItemDisable,
onTabToolItemClick
};
}
});
</script>
文件目录结构如下图
最后再到运行路径中导入该组件
这里以启动工程的 main.ts 举例,如果运行时未看到该组件的效果,请检查是否正确导入到运行时的路径中
Oinone社区 作者:史, 昂原创文章,如若转载,请注明出处:https://doc.oinone.top/oio4/9272.html
访问Oinone官网:https://www.oinone.top获取数式Oinone低代码应用平台体验