✨(component): [tabitem] 新增 icon 属性
This commit is contained in:
parent
993d657cf3
commit
e1a41552c5
@ -14,10 +14,7 @@ export default (): UserConfigExport => {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
plugins: [
|
plugins: [vue(), vueJsx()],
|
||||||
vue(),
|
|
||||||
vueJsx(),
|
|
||||||
],
|
|
||||||
build: {
|
build: {
|
||||||
cssCodeSplit: false,
|
cssCodeSplit: false,
|
||||||
outDir: "lib",
|
outDir: "lib",
|
||||||
|
@ -26,6 +26,7 @@ import {
|
|||||||
h,
|
h,
|
||||||
createTextVNode,
|
createTextVNode,
|
||||||
isVNode,
|
isVNode,
|
||||||
|
Fragment,
|
||||||
} from "vue";
|
} from "vue";
|
||||||
import { useResizeObserver } from "@vueuse/core";
|
import { useResizeObserver } from "@vueuse/core";
|
||||||
import { TabData, TabInjectKey } from "./interface";
|
import { TabData, TabInjectKey } from "./interface";
|
||||||
@ -44,7 +45,6 @@ export interface LayTabProps {
|
|||||||
|
|
||||||
const slot = useSlots();
|
const slot = useSlots();
|
||||||
const childrens: Ref<VNode[]> = ref([]);
|
const childrens: Ref<VNode[]> = ref([]);
|
||||||
const slotsChange = ref(true);
|
|
||||||
const tabMap = reactive(new Map<number, TabData>());
|
const tabMap = reactive(new Map<number, TabData>());
|
||||||
|
|
||||||
const setItemInstanceBySlot = function (nodeList: VNode[]) {
|
const setItemInstanceBySlot = function (nodeList: VNode[]) {
|
||||||
@ -266,16 +266,27 @@ const update = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const renderTabChild = (child: TabData) => {
|
const renderTabIcon = (attrs: Record<string, unknown>) => {
|
||||||
if (child.slots?.title) {
|
const tab = attrs.tabData as TabData;
|
||||||
return () => h("span", child.slots?.title && child.slots.title());
|
if (typeof tab.icon === "function") {
|
||||||
|
return tab.icon();
|
||||||
|
} else if (typeof tab.icon === "string") {
|
||||||
|
return h(LayIcon, {
|
||||||
|
type: tab.icon,
|
||||||
|
style: "margin-right: 8px;",
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
if (typeof child.title === "function") {
|
const renderTabTitle = (attrs: Record<string, unknown>) => {
|
||||||
// @ts-ignore
|
const tab = attrs.tabData as TabData;
|
||||||
return () => child.title();
|
if (tab.slots?.title) {
|
||||||
} else if (typeof child.title === "string") {
|
return h(Fragment, tab.slots?.title && tab.slots.title());
|
||||||
return () => createTextVNode(child.title as string);
|
}
|
||||||
|
if (typeof tab.title === "function") {
|
||||||
|
return tab.title();
|
||||||
|
} else if (typeof tab.title === "string") {
|
||||||
|
return createTextVNode(tab.title as string);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -309,7 +320,6 @@ onMounted(() => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
provide("active", active);
|
provide("active", active);
|
||||||
provide("slotsChange", slotsChange);
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@ -339,16 +349,23 @@ provide("slotsChange", slotsChange);
|
|||||||
:style="tabBarStyle"
|
:style="tabBarStyle"
|
||||||
></div>
|
></div>
|
||||||
<li
|
<li
|
||||||
v-for="(children, index) in tabItems"
|
v-for="(child, index) in tabItems"
|
||||||
:key="children.id"
|
:key="child.id"
|
||||||
:class="[children.id === active ? 'layui-this' : '']"
|
:class="[child.id === active ? 'layui-this' : '']"
|
||||||
@click.stop="change(children.id)"
|
@click.stop="change(child.id)"
|
||||||
>
|
>
|
||||||
<RenderFunction :renderFunc="renderTabChild(children)" />
|
<span>
|
||||||
|
<RenderFunction
|
||||||
|
v-if="child['icon']"
|
||||||
|
:renderFunc="renderTabIcon"
|
||||||
|
:tabData="child"
|
||||||
|
/>
|
||||||
|
<RenderFunction :renderFunc="renderTabTitle" :tabData="child" />
|
||||||
|
</span>
|
||||||
<i
|
<i
|
||||||
v-if="allowClose && children.closable != false"
|
v-if="allowClose && child.closable != false"
|
||||||
class="layui-icon layui-icon-close layui-unselect layui-tab-close"
|
class="layui-icon layui-icon-close layui-unselect layui-tab-close"
|
||||||
@click.stop="close(index, children.id)"
|
@click.stop="close(index, child.id)"
|
||||||
></i>
|
></i>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
@ -5,6 +5,7 @@ export const TabInjectKey = Symbol("layuiTab");
|
|||||||
export interface TabData {
|
export interface TabData {
|
||||||
id: string;
|
id: string;
|
||||||
title?: string | Function;
|
title?: string | Function;
|
||||||
|
icon?: string | Function;
|
||||||
closable?: string | boolean;
|
closable?: string | boolean;
|
||||||
slots: Slots;
|
slots: Slots;
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,7 @@ import { TabInjectKey, TabsContext } from "../tab/interface";
|
|||||||
export interface LayTabItemProps {
|
export interface LayTabItemProps {
|
||||||
id: string;
|
id: string;
|
||||||
title?: string | Function;
|
title?: string | Function;
|
||||||
|
icon?: string | Function;
|
||||||
closable?: boolean | string;
|
closable?: boolean | string;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -31,13 +32,12 @@ const props = withDefaults(defineProps<LayTabItemProps>(), {
|
|||||||
const instance = getCurrentInstance();
|
const instance = getCurrentInstance();
|
||||||
const slots = useSlots();
|
const slots = useSlots();
|
||||||
const active = inject("active");
|
const active = inject("active");
|
||||||
const slotsChange: Ref<boolean> = inject("slotsChange") as Ref<boolean>;
|
|
||||||
slotsChange.value = !slotsChange.value;
|
|
||||||
const tabsCtx = inject<Partial<TabsContext>>(TabInjectKey, {});
|
const tabsCtx = inject<Partial<TabsContext>>(TabInjectKey, {});
|
||||||
|
|
||||||
const data = reactive({
|
const data = reactive({
|
||||||
id: props.id,
|
id: props.id,
|
||||||
title: props.title,
|
title: props.title,
|
||||||
|
icon: props.icon,
|
||||||
closable: props.closable,
|
closable: props.closable,
|
||||||
slots: slots,
|
slots: slots,
|
||||||
});
|
});
|
||||||
|
@ -36,63 +36,65 @@ export default {
|
|||||||
|
|
||||||
:::
|
:::
|
||||||
|
|
||||||
::: title 标题插槽
|
::: title 图标
|
||||||
:::
|
:::
|
||||||
|
|
||||||
::: demo 通过 `allow-close` 属性, 启用选项可关闭。
|
::: demo 通过 `icon` 属性, 快速设置前置图标, 也可通过 title 插槽实现。
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<lay-tab v-model="current11" :allow-close="true">
|
<lay-tab v-model="current11" :allow-close="true">
|
||||||
<lay-tab-item id="1">
|
<lay-tab-item id="1" title="选项一">
|
||||||
<template #title>
|
|
||||||
<lay-icon type="layui-icon-console"></lay-icon>
|
|
||||||
<span style="margin-left:10px">选项一</span>
|
|
||||||
</template>
|
|
||||||
<div style="padding:20px">选项一</div>
|
<div style="padding:20px">选项一</div>
|
||||||
</lay-tab-item>
|
</lay-tab-item>
|
||||||
<lay-tab-item id="2">
|
<lay-tab-item id="2" title="选项二" icon="layui-icon-console">
|
||||||
<template #title>
|
|
||||||
<lay-icon type="layui-icon-user"></lay-icon>
|
|
||||||
<span style="margin-left:10px">选项二</span>
|
|
||||||
</template>
|
|
||||||
<div style="padding:20px">选项二</div>
|
<div style="padding:20px">选项二</div>
|
||||||
</lay-tab-item>
|
</lay-tab-item>
|
||||||
<lay-tab-item id="3">
|
<lay-tab-item id="3" title="选项三" :icon="renderIconFunc">
|
||||||
<template #title>
|
|
||||||
<lay-icon type="layui-icon-set"></lay-icon>
|
|
||||||
<span style="margin-left:10px">选项三</span>
|
|
||||||
</template>
|
|
||||||
<div style="padding:20px">选项三</div>
|
<div style="padding:20px">选项三</div>
|
||||||
</lay-tab-item>
|
</lay-tab-item>
|
||||||
<lay-tab-item id="4" :title="renderTitleFunc">
|
<lay-tab-item id="4">
|
||||||
|
<template #title>
|
||||||
|
选项四
|
||||||
|
<lay-icon type="layui-icon-set" style="margin-left:8px"></lay-icon>
|
||||||
|
</template>
|
||||||
<div style="padding:20px">选项四</div>
|
<div style="padding:20px">选项四</div>
|
||||||
</lay-tab-item>
|
</lay-tab-item>
|
||||||
|
<lay-tab-item id="5" :title="renderTitleFunc">
|
||||||
|
<div style="padding:20px">选项五</div>
|
||||||
|
</lay-tab-item>
|
||||||
</lay-tab>
|
</lay-tab>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { ref,h , resolveComponent} from 'vue'
|
import { ref,h , Fragment,resolveComponent} from 'vue'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
setup() {
|
setup() {
|
||||||
const LayIcon = resolveComponent("LayIcon");
|
const LayIcon = resolveComponent("LayIcon");
|
||||||
|
|
||||||
const current11 = ref("1")
|
const current11 = ref("1")
|
||||||
|
|
||||||
|
const renderIconFunc = () => h("span", {
|
||||||
|
style: "margin-right: 8px;"
|
||||||
|
},"🚧");
|
||||||
|
|
||||||
const renderTitleFunc = () => [
|
const renderTitleFunc = () => [
|
||||||
h(LayIcon,
|
h(LayIcon,
|
||||||
{
|
{
|
||||||
type: "layui-icon-component",
|
type: "layui-icon-component",
|
||||||
|
style: "margin-right: 8px;",
|
||||||
}),
|
}),
|
||||||
h("span",
|
h("span",
|
||||||
{
|
{
|
||||||
style: "margin-left: 10px; color: red",
|
style: "color: red",
|
||||||
},
|
},
|
||||||
"选项四")
|
"选项五"),
|
||||||
]
|
]
|
||||||
|
|
||||||
return {
|
return {
|
||||||
current11,
|
current11,
|
||||||
renderTitleFunc
|
renderTitleFunc,
|
||||||
|
renderIconFunc,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -418,7 +420,8 @@ export default {
|
|||||||
| 属性 | 描述 | 类型 | 默认值 | 可选值 |
|
| 属性 | 描述 | 类型 | 默认值 | 可选值 |
|
||||||
| -------- | --------------------- | ---------------- | ------- | -------------- |
|
| -------- | --------------------- | ---------------- | ------- | -------------- |
|
||||||
| id | 唯一标识 | `string` | - | - |
|
| id | 唯一标识 | `string` | - | - |
|
||||||
| title | 头部标题,支持渲染函数 | `string` `vnode` | - | - |
|
| title | 头部标题 | `string` `VNode` | - | - |
|
||||||
|
| icon | 前置图标| `string` `VNode`
|
||||||
| closable | 允许关闭 | `boolean` | `false` | `true` `false` |
|
| closable | 允许关闭 | `boolean` | `false` | `true` `false` |
|
||||||
|
|
||||||
:::
|
:::
|
||||||
|
Loading…
Reference in New Issue
Block a user