✨(component): [Tag}新增 Tag 组件
This commit is contained in:
parent
48cacb8d91
commit
24b2cbd143
88
package/component/src/component/tag/index.less
Normal file
88
package/component/src/component/tag/index.less
Normal file
@ -0,0 +1,88 @@
|
||||
@tag-size-default: 24px;
|
||||
@tag-size-default-font-size: 12px;
|
||||
@tag-size-lg: @tag-size-default + 2px;
|
||||
@tag-size-md: @tag-size-default;
|
||||
@tag-size-sm: @tag-size-default - 2px;
|
||||
@tag-size-xs: @tag-size-default - 2px * 2;
|
||||
@tag-size-lg-font-size: @tag-size-default-font-size + 2px;
|
||||
@tag-size-md-font-size: @tag-size-default-font-size;
|
||||
@tag-size-sm-font-size: @tag-size-default-font-size - 2px;
|
||||
@tag-size-xs-font-size: @tag-size-default-font-size - 2px * 2;
|
||||
@tag-border-width: 1px;
|
||||
|
||||
.layui-tag {
|
||||
display: inline-flex;
|
||||
align-items: baseline;
|
||||
vertical-align: middle;
|
||||
box-sizing: border-box;
|
||||
height: @tag-size-md;
|
||||
line-height: @tag-size-md - @tag-border-width * 2;
|
||||
padding: 0 6px;
|
||||
font-size: @tag-size-md-font-size;
|
||||
font-weight: 500;
|
||||
color: currentColor;
|
||||
border-width: @tag-border-width;
|
||||
border-style: solid;
|
||||
border-color: transparent;
|
||||
border-radius: var(--global-border-radius);
|
||||
|
||||
&-icon {
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
&-bordered {
|
||||
border-color: var(--global-neutral-color-5);
|
||||
}
|
||||
|
||||
&-size-lg {
|
||||
height: @tag-size-lg;
|
||||
font-size: @tag-size-lg-font-size;
|
||||
line-height: @tag-size-lg - @tag-border-width * 2;
|
||||
|
||||
.layui-icon {
|
||||
font-size: @tag-size-lg-font-size - 2px;
|
||||
}
|
||||
}
|
||||
|
||||
&-size-md {
|
||||
height: @tag-size-md;
|
||||
font-size: @tag-size-md-font-size;
|
||||
line-height: @tag-size-md - @tag-border-width * 2;
|
||||
|
||||
.layui-icon {
|
||||
font-size: @tag-size-md-font-size - 2px;
|
||||
}
|
||||
}
|
||||
|
||||
&-size-sm {
|
||||
height: @tag-size-sm;
|
||||
font-size: @tag-size-sm-font-size;
|
||||
line-height: @tag-size-sm - @tag-border-width * 2;
|
||||
|
||||
.layui-icon {
|
||||
font-size: @tag-size-sm-font-size - 2px;
|
||||
}
|
||||
}
|
||||
|
||||
&-size-xs {
|
||||
height: @tag-size-xs;
|
||||
font-size: @tag-size-xs-font-size;
|
||||
line-height: @tag-size-xs - @tag-border-width * 2;
|
||||
|
||||
.layui-icon {
|
||||
font-size: @tag-size-xs-font-size - 2px;
|
||||
}
|
||||
}
|
||||
|
||||
& &-close-icon {
|
||||
margin-left: 4px;
|
||||
font-size: @tag-size-default-font-size - 2px;
|
||||
|
||||
.layui-icon {
|
||||
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
5
package/component/src/component/tag/index.ts
Normal file
5
package/component/src/component/tag/index.ts
Normal file
@ -0,0 +1,5 @@
|
||||
import { withInstall, WithInstallType } from "../../utils";
|
||||
import Component from "./index.vue";
|
||||
|
||||
const component: WithInstallType<typeof Component> = withInstall(Component);
|
||||
export default component;
|
71
package/component/src/component/tag/index.vue
Normal file
71
package/component/src/component/tag/index.vue
Normal file
@ -0,0 +1,71 @@
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: "LayTag",
|
||||
};
|
||||
</script>
|
||||
<script lang="ts" setup>
|
||||
import "./index.less";
|
||||
import { LayIcon } from "@layui/icons-vue";
|
||||
import { computed, ref } from "vue";
|
||||
import { TAG_COLORS, TagColor } from "./interface";
|
||||
|
||||
export interface LayTagProps {
|
||||
color?: TagColor | string;
|
||||
closable?: boolean;
|
||||
size?: string;
|
||||
bordered?: boolean;
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<LayTagProps>(), {
|
||||
color: "green",
|
||||
size: "md",
|
||||
closable: false,
|
||||
bordered: false,
|
||||
});
|
||||
|
||||
const emit = defineEmits(["close"]);
|
||||
|
||||
const isBuiltInColor = computed(
|
||||
() => props.color && TAG_COLORS.includes(props.color as any)
|
||||
);
|
||||
const isCustomColor = computed(
|
||||
() => props.color && !TAG_COLORS.includes(props.color as any)
|
||||
);
|
||||
|
||||
const visible = ref(true);
|
||||
|
||||
const handleClose = (e: MouseEvent) => {
|
||||
//visible.value = false;
|
||||
emit("close", e);
|
||||
};
|
||||
|
||||
const classTag = computed(() => [
|
||||
"layui-tag",
|
||||
`layui-tag-size-${props.size}`,
|
||||
{
|
||||
[`layui-bg-${props.color}`]: isBuiltInColor,
|
||||
"layui-tag-bordered": props.bordered,
|
||||
},
|
||||
]);
|
||||
|
||||
const styleTag = computed(() => {
|
||||
return isCustomColor.value ? { backgroundColor: props.color } : undefined;
|
||||
});
|
||||
</script>
|
||||
<template>
|
||||
<span v-if="visible" :class="classTag" :style="styleTag">
|
||||
<span v-if="$slots.icon" class="layui-tag-icon">
|
||||
<slot name="icon" />
|
||||
</span>
|
||||
<slot />
|
||||
<span
|
||||
v-if="closable"
|
||||
class="layui-tag-close-icon"
|
||||
@click.stop="handleClose"
|
||||
>
|
||||
<slot name="close-icon">
|
||||
<lay-icon type="layui-icon-close"></lay-icon>
|
||||
</slot>
|
||||
</span>
|
||||
</span>
|
||||
</template>
|
11
package/component/src/component/tag/interface.ts
Normal file
11
package/component/src/component/tag/interface.ts
Normal file
@ -0,0 +1,11 @@
|
||||
export const TAG_COLORS = [
|
||||
"red",
|
||||
"orange",
|
||||
"green",
|
||||
"cyan",
|
||||
"blue",
|
||||
"black",
|
||||
"gray",
|
||||
] as const;
|
||||
|
||||
export type TagColor = typeof TAG_COLORS[number];
|
64
package/component/src/component/tagInput/Tag.vue
Normal file
64
package/component/src/component/tagInput/Tag.vue
Normal file
@ -0,0 +1,64 @@
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: "Tag",
|
||||
};
|
||||
</script>
|
||||
<script lang="ts" setup>
|
||||
import { ref } from "vue";
|
||||
|
||||
export interface LayTagProps {
|
||||
theme?: string;
|
||||
closable?: boolean;
|
||||
size?: string;
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<LayTagProps>(), {
|
||||
closable: true,
|
||||
});
|
||||
|
||||
const emit = defineEmits(["close"]);
|
||||
|
||||
const visible = ref(true);
|
||||
|
||||
const handleClose = (e: MouseEvent) => {
|
||||
visible.value = false;
|
||||
emit("close", e);
|
||||
};
|
||||
</script>
|
||||
<template>
|
||||
<lay-badge v-if="visible" theme="green">
|
||||
<template v-if="$slots.default" #default>
|
||||
<slot name="default"></slot>
|
||||
<lay-icon
|
||||
v-if="closable"
|
||||
type="layui-icon-close"
|
||||
@click.stop="handleClose"
|
||||
></lay-icon>
|
||||
</template>
|
||||
</lay-badge>
|
||||
</template>
|
||||
|
||||
<!-- <template v-for="(item, index) in selectItem.label" :key="index">
|
||||
<lay-badge theme="green">
|
||||
<span>{{ item }}</span>
|
||||
<i
|
||||
:class="['layui-icon', { 'layui-icon-close': true }]"
|
||||
v-if="
|
||||
!disabled &&
|
||||
!(
|
||||
Array.isArray(selectItem.value) &&
|
||||
selectItem.value.length > 0 &&
|
||||
disabledItemMap[selectItem.value[index]]
|
||||
)
|
||||
"
|
||||
@click="
|
||||
removeItemHandle($event, {
|
||||
label: item,
|
||||
value: Array.isArray(selectItem.value)
|
||||
? selectItem.value[index]
|
||||
: null,
|
||||
})
|
||||
"
|
||||
></i>
|
||||
</lay-badge>
|
||||
</template> -->
|
65
package/component/src/component/tagInput/index.less
Normal file
65
package/component/src/component/tagInput/index.less
Normal file
@ -0,0 +1,65 @@
|
||||
.layui-input-tag {
|
||||
position: relative;
|
||||
display: block;
|
||||
padding: 0 5px;
|
||||
height: auto;
|
||||
overflow: hidden;
|
||||
|
||||
.layui-input-prefix {
|
||||
display: inline;
|
||||
text-align: left;
|
||||
height: 100%;
|
||||
flex: unset;
|
||||
}
|
||||
|
||||
.layui-input-suffix{
|
||||
position: absolute;
|
||||
right: 3px;
|
||||
bottom: 0;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.layui-input {
|
||||
display: inline-block;
|
||||
padding-left: 0;
|
||||
width: auto;
|
||||
flex: 1;
|
||||
max-width: 100%;
|
||||
min-width: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
.layui-input-tag-collapsed-panel,
|
||||
.layui-input-tag {
|
||||
.layui-badge {
|
||||
margin-right: 5px;
|
||||
height: 28px;
|
||||
line-height: 28px;
|
||||
user-select: none;
|
||||
white-space: pre-wrap;
|
||||
|
||||
.layui-icon {
|
||||
font-size: 12px;
|
||||
padding-left: 3px;
|
||||
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
color: #ff5722;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.layui-input-tag-collapsed-panel {
|
||||
white-space: normal;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
width: fit-content;
|
||||
max-width: 200px;
|
||||
height: auto;
|
||||
overflow: hidden;
|
||||
.layui-badge{
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
}
|
5
package/component/src/component/tagInput/index.ts
Normal file
5
package/component/src/component/tagInput/index.ts
Normal file
@ -0,0 +1,5 @@
|
||||
import { withInstall, WithInstallType } from "../../utils";
|
||||
import Component from "./index.vue";
|
||||
|
||||
const component: WithInstallType<typeof Component> = withInstall(Component);
|
||||
export default component;
|
158
package/component/src/component/tagInput/index.vue
Normal file
158
package/component/src/component/tagInput/index.vue
Normal file
@ -0,0 +1,158 @@
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: "LayInputTag",
|
||||
};
|
||||
</script>
|
||||
<script lang="ts" setup>
|
||||
import "./index.less";
|
||||
import Tag from "./Tag.vue";
|
||||
import LayToopTip from "../tooltip/index.vue";
|
||||
import { onMounted, shallowRef, ref, watch, computed } from "vue";
|
||||
|
||||
export interface TagData {
|
||||
value?: string | number;
|
||||
label?: string;
|
||||
closable?: boolean;
|
||||
[other: string]: any;
|
||||
}
|
||||
|
||||
export interface LayInputTagProps {
|
||||
modelValue?: TagData[];
|
||||
inputValue?: string;
|
||||
disabled?: boolean;
|
||||
placeholder?: string;
|
||||
readonly?: boolean;
|
||||
allowClear?: boolean;
|
||||
max?: number;
|
||||
minCollapsedNum?: number;
|
||||
collapseTagsTooltip?: boolean;
|
||||
size?: "md" | "sm" | "xs";
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<LayInputTagProps>(), {
|
||||
disabled: false,
|
||||
placeholder: "",
|
||||
readonly: false,
|
||||
allowClear: true,
|
||||
minCollapsedNum: 10,
|
||||
//max:3
|
||||
});
|
||||
|
||||
const emit = defineEmits(["update:modelValue", "update:inputValue"]);
|
||||
|
||||
const mirrorRef = shallowRef<HTMLElement | undefined>(undefined);
|
||||
const inputRef = shallowRef<HTMLElement | undefined>(undefined);
|
||||
|
||||
const tagData = ref<TagData[]>(props.modelValue ?? []);
|
||||
const inputValue = ref<string>();
|
||||
const oldInputValue = ref<string>();
|
||||
|
||||
const computedTagData = computed(() => {
|
||||
return props.minCollapsedNum
|
||||
? tagData.value?.slice(0, props.minCollapsedNum)
|
||||
: tagData.value;
|
||||
});
|
||||
|
||||
const collapsedTagData = computed(() => {
|
||||
return props.minCollapsedNum && tagData.value?.length > props.minCollapsedNum
|
||||
? tagData.value?.slice(props.minCollapsedNum)
|
||||
: [];
|
||||
});
|
||||
|
||||
const handleInputEnter = (e: KeyboardEvent) => {
|
||||
e.preventDefault();
|
||||
const valueStr = inputValue.value ? String(inputValue.value).trim() : "";
|
||||
if (!valueStr || !tagData.value) return;
|
||||
const isLimit = props.max && tagData.value?.length >= props.max;
|
||||
if (!isLimit) {
|
||||
tagData.value =
|
||||
tagData.value instanceof Array
|
||||
? tagData.value.concat(String(valueStr))
|
||||
: [valueStr];
|
||||
inputValue.value = "";
|
||||
}
|
||||
};
|
||||
|
||||
const handlerInputBackspaceKeyUp = (e: KeyboardEvent) => {
|
||||
if (!tagData.value || !tagData.value.length) return;
|
||||
if (!oldInputValue.value && ["Backspace", "Delete"].includes(e.code)) {
|
||||
tagData.value = tagData.value.slice(0, -1);
|
||||
}
|
||||
oldInputValue.value = inputValue.value;
|
||||
};
|
||||
|
||||
const handlerClearClick = (e: MouseEvent) => {
|
||||
tagData.value = [];
|
||||
};
|
||||
|
||||
const handlerClose = (index: number) => {
|
||||
if (!tagData.value) return;
|
||||
const arr = [...tagData.value];
|
||||
arr.splice(index, 1);
|
||||
tagData.value = arr;
|
||||
};
|
||||
|
||||
const handlerFocus = (e: MouseEvent) => {
|
||||
(
|
||||
(e.target as HTMLElement).querySelector(".layui-input") as HTMLInputElement
|
||||
)?.focus();
|
||||
};
|
||||
|
||||
watch(tagData, (val) => {
|
||||
emit("update:modelValue", val);
|
||||
});
|
||||
|
||||
watch(inputValue, (val) => {
|
||||
emit("update:inputValue", val);
|
||||
});
|
||||
|
||||
onMounted(() => {});
|
||||
</script>
|
||||
<template>
|
||||
<lay-input
|
||||
class="layui-input-tag"
|
||||
v-model="inputValue"
|
||||
:placeholder="placeholder"
|
||||
:readonly="readonly"
|
||||
@keydown.enter="handleInputEnter"
|
||||
@keyup="handlerInputBackspaceKeyUp"
|
||||
@click="handlerFocus"
|
||||
>
|
||||
<template #prefix>
|
||||
<template
|
||||
v-for="(item, index) of computedTagData"
|
||||
:key="`${item}-${index}`"
|
||||
>
|
||||
<Tag :closable="!readonly" @close="handlerClose(index)">
|
||||
{{ item }}
|
||||
</Tag>
|
||||
</template>
|
||||
<template v-if="computedTagData?.length != tagData?.length">
|
||||
<LayToopTip :isDark="false">
|
||||
<Tag key="more" :closable="false"
|
||||
>+{{ tagData?.length - computedTagData?.length }}...</Tag
|
||||
>
|
||||
<template #content>
|
||||
<div class="layui-input-tag-collapsed-panel">
|
||||
<template
|
||||
v-for="(item, index) of tagData"
|
||||
:key="`${item}-${index}`"
|
||||
>
|
||||
<Tag
|
||||
v-if="index >= minCollapsedNum"
|
||||
:closable="!readonly"
|
||||
@close="handlerClose(index)"
|
||||
>
|
||||
{{ item }}
|
||||
</Tag>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
</LayToopTip>
|
||||
</template>
|
||||
</template>
|
||||
<template #suffix v-if="allowClear && tagData?.length">
|
||||
<lay-icon type="layui-icon-close-fill" @click.stop="handlerClearClick" />
|
||||
</template>
|
||||
</lay-input>
|
||||
</template>
|
@ -88,6 +88,7 @@ import LayNoticeBar from "./component/noticeBar/index";
|
||||
import LayPageHeader from "./component/pageHeader/index";
|
||||
import LayCascader from "./component/cascader/index";
|
||||
import LayAffix from "./component/affix/index";
|
||||
import LayTag from "./component/tag/index";
|
||||
import LayConfigProvider from "./provider";
|
||||
import { InstallOptions } from "./types";
|
||||
|
||||
@ -174,6 +175,7 @@ const components: Record<string, Plugin> = {
|
||||
LayPageHeader,
|
||||
LayCascader,
|
||||
LayAffix,
|
||||
LayTag,
|
||||
};
|
||||
|
||||
const install = (app: App, options?: InstallOptions): void => {
|
||||
@ -267,6 +269,7 @@ export {
|
||||
LayPageHeader,
|
||||
LayCascader,
|
||||
LayAffix,
|
||||
LayTag,
|
||||
install,
|
||||
};
|
||||
|
||||
|
313
package/document-component/src/document/zh-CN/components/tag.md
Normal file
313
package/document-component/src/document/zh-CN/components/tag.md
Normal file
@ -0,0 +1,313 @@
|
||||
::: anchor
|
||||
:::
|
||||
|
||||
::: title 基本介绍
|
||||
:::
|
||||
|
||||
::: describe 标签组件。
|
||||
:::
|
||||
|
||||
::: title 基础使用
|
||||
:::
|
||||
|
||||
::: demo 标签的基本用法。
|
||||
|
||||
<template>
|
||||
<lay-tag>tag</lay-tag>
|
||||
  
|
||||
<lay-tag bordered color="#FFF">tag</lay-tag>
|
||||
  
|
||||
<lay-tag closable>tag</lay-tag>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
</script>
|
||||
|
||||
:::
|
||||
|
||||
::: title 标签尺寸
|
||||
:::
|
||||
|
||||
::: demo 通过 size 属性控制标签尺寸。
|
||||
|
||||
<template>
|
||||
<lay-tag>default</lay-tag>
|
||||
  
|
||||
<lay-tag size="lg">tag lg</lay-tag>
|
||||
  
|
||||
<lay-tag size="md">tag md</lay-tag>
|
||||
  
|
||||
<lay-tag size="sm">tag sm</lay-tag>
|
||||
  
|
||||
<lay-tag size="xs">tag xs</lay-tag>
|
||||
<br><br>
|
||||
<lay-tag><template #icon><lay-icon type="layui-icon-addition" /></template>default</lay-tag>
|
||||
  
|
||||
<lay-tag size="lg"><template #icon><lay-icon type="layui-icon-addition" /></template>tag lg</lay-tag>
|
||||
  
|
||||
<lay-tag size="md"><template #icon><lay-icon type="layui-icon-addition" /></template>tag md</lay-tag>
|
||||
  
|
||||
<lay-tag size="sm"><template #icon><lay-icon type="layui-icon-addition" /></template>tag sm</lay-tag>
|
||||
  
|
||||
<lay-tag size="xs"><template #icon><lay-icon type="layui-icon-addition" /></template>tag xs</lay-tag>
|
||||
<br><br>
|
||||
<lay-tag closable>
|
||||
<template #icon><lay-icon type="layui-icon-addition" /></template>
|
||||
default
|
||||
</lay-tag>
|
||||
  
|
||||
<lay-tag size="lg" closable>
|
||||
<template #icon><lay-icon type="layui-icon-addition" /></template>
|
||||
tag lg
|
||||
</lay-tag>
|
||||
  
|
||||
<lay-tag size="md" closable>
|
||||
<template #icon><lay-icon type="layui-icon-addition" /></template>
|
||||
tag md
|
||||
</lay-tag>
|
||||
  
|
||||
<lay-tag size="sm" closable>
|
||||
<template #icon><lay-icon type="layui-icon-addition" /></template>
|
||||
tag sm
|
||||
</lay-tag>
|
||||
  
|
||||
<lay-tag size="xs" closable>
|
||||
<template #icon><lay-icon type="layui-icon-addition" /></template>
|
||||
tag xs
|
||||
</lay-tag>
|
||||
  
|
||||
</template>
|
||||
|
||||
<script>
|
||||
</script>
|
||||
|
||||
:::
|
||||
|
||||
::: title 可关闭
|
||||
:::
|
||||
|
||||
::: demo 通过 closable 属性控制标签是否可关闭
|
||||
|
||||
<template>
|
||||
<lay-tag closable>Tag</lay-tag>
|
||||
  
|
||||
<lay-tag closable>
|
||||
<template #icon><lay-icon type="layui-icon-addition" /></template>
|
||||
Tag 2
|
||||
</lay-tag>
|
||||
  
|
||||
<lay-tag closable>
|
||||
<template #icon><lay-icon type="layui-icon-addition" /></template>
|
||||
自定义关闭图标
|
||||
<template #close-icon><lay-icon type="layui-icon-close-fill" /></template>
|
||||
</lay-tag>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
</script>
|
||||
|
||||
:::
|
||||
|
||||
::: title 标签颜色
|
||||
:::
|
||||
|
||||
::: demo 标签颜色,待优化。
|
||||
|
||||
<template>
|
||||
<span v-for="color in TAG_COLORS">
|
||||
<lay-tag :color="color">Tag</lay-tag>
|
||||
  
|
||||
</span>
|
||||
<br><br>
|
||||
<span v-for="color in TAG_COLORS">
|
||||
<lay-tag :color="color" bordered>Tag</lay-tag>
|
||||
  
|
||||
</span>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { ref } from 'vue'
|
||||
|
||||
export default {
|
||||
setup() {
|
||||
|
||||
const TAG_COLORS = [
|
||||
"red",
|
||||
"orange",
|
||||
"green",
|
||||
"cyan",
|
||||
"blue",
|
||||
"black",
|
||||
"gray",
|
||||
"#EEE",
|
||||
"#5FB878",
|
||||
"#FFB800",
|
||||
];
|
||||
|
||||
return {
|
||||
TAG_COLORS
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
:::
|
||||
|
||||
::: title 图标插槽
|
||||
:::
|
||||
|
||||
::: demo 标签的基本用法。
|
||||
|
||||
<template>
|
||||
<lay-tag bordered size="lg" color="#FFF">
|
||||
<template #icon>
|
||||
<lay-icon type="layui-icon-vercode" />
|
||||
</template>
|
||||
tag
|
||||
</lay-tag>
|
||||
  
|
||||
<lay-tag bordered size="lg" color="#FFF">
|
||||
<template #icon>
|
||||
<lay-icon type="layui-icon-login-qq" />
|
||||
</template>
|
||||
tag
|
||||
</lay-tag>
|
||||
  
|
||||
<lay-tag bordered size="lg" color="#FFF">
|
||||
<template #icon>
|
||||
<lay-icon type="layui-icon-star-fill" />
|
||||
</template>
|
||||
tag
|
||||
</lay-tag>
|
||||
  
|
||||
</template>
|
||||
|
||||
<script>
|
||||
</script>
|
||||
|
||||
:::
|
||||
|
||||
::: title 动态编辑
|
||||
:::
|
||||
|
||||
::: demo 标签的基本用法。
|
||||
|
||||
<template>
|
||||
{{ tagData }}
|
||||
<br><br>
|
||||
<template v-for="(tag, index) of tagData" :key="`tag-${index}`">
|
||||
<lay-tag
|
||||
closable
|
||||
@close="handleClose(index)"
|
||||
color="#EEE"
|
||||
style="margin-right: 5px;"
|
||||
>
|
||||
{{tag}}
|
||||
</lay-tag>
|
||||
</template>
|
||||
<span id="tagDemo" @click="handlerFocus">
|
||||
<lay-input
|
||||
v-if="showInput"
|
||||
ref="inputRef"
|
||||
v-model.trim="inputVal"
|
||||
autofocus
|
||||
style="width:60px; height:24px"
|
||||
@keyup.enter="handleAdd"
|
||||
@blur="handleAdd" />
|
||||
<lay-tag
|
||||
v-else
|
||||
color="#EEE"
|
||||
>
|
||||
<template #icon>
|
||||
<lay-icon type="layui-icon-addition"/>
|
||||
</template>
|
||||
添加
|
||||
</lay-tag>
|
||||
</span>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { ref, nextTick } from 'vue';
|
||||
|
||||
export default {
|
||||
setup() {
|
||||
const tagData = ref(['Tag']);
|
||||
const inputRef = ref(null);
|
||||
const showInput = ref(false);
|
||||
const inputVal = ref('');
|
||||
|
||||
const handleAdd = () => {
|
||||
if (inputVal.value) {
|
||||
tagData.value.push(inputVal.value);
|
||||
inputVal.value = '';
|
||||
}
|
||||
showInput.value = false;
|
||||
};
|
||||
|
||||
const handleClose = (index) => {
|
||||
tagData.value.splice(index, 1);
|
||||
};
|
||||
|
||||
const handlerFocus = (e) => {
|
||||
showInput.value = true;
|
||||
console.log("FIXME 临时")
|
||||
setTimeout(() => {
|
||||
document.querySelector('#tagDemo input').focus()
|
||||
},200)
|
||||
|
||||
}
|
||||
|
||||
return {
|
||||
tagData,
|
||||
inputRef,
|
||||
showInput,
|
||||
inputVal,
|
||||
handleAdd,
|
||||
handleClose,
|
||||
handlerFocus,
|
||||
};
|
||||
},
|
||||
};
|
||||
</script>
|
||||
:::
|
||||
|
||||
|
||||
::: title Tag 属性
|
||||
:::
|
||||
|
||||
::: table
|
||||
|
||||
| 属性 | 描述 | 类型 | 默认值 | 可选值 |
|
||||
| ----------- | -------- | ------ | ------ | ------ |
|
||||
| size | 标签大小 | string | md | `lg` `md` `sm` `xs`|
|
||||
| color | 标签颜色 | string | `green`| `red` `orange` `green` `cyan` `blue` `black` `gray` `string` |
|
||||
| bordered | 是否显示边框 | boolean | false | `true` `false`|
|
||||
| closable | 是否可关闭 | boolean | false | `true` `false`|
|
||||
|
||||
:::
|
||||
|
||||
:::title Tag 插槽
|
||||
:::
|
||||
|
||||
:::table
|
||||
| 插槽 | 描述 | 参数 |
|
||||
|------ |----------|-----------|
|
||||
| default | 默认插槽 | - |
|
||||
| icon | 图标 | - |
|
||||
| close-icon | 关闭图标 | - |
|
||||
:::
|
||||
|
||||
:::title Tag 事件
|
||||
:::
|
||||
|
||||
:::table
|
||||
| 事件 | 描述 | 参数 |
|
||||
|------ |----------|-----------|
|
||||
| close | 关闭时触发 | e: MouseEvent |
|
||||
:::
|
||||
|
||||
::: contributor tag
|
||||
:::
|
||||
|
||||
::: previousNext tag
|
||||
:::
|
@ -419,6 +419,11 @@ const zhCN = [
|
||||
component: () => import("../document/zh-CN/components/photo.md"),
|
||||
meta: { title: "相册" },
|
||||
},
|
||||
{
|
||||
path: "/zh-CN/components/tag",
|
||||
component: () => import("../document/zh-CN/components/tag.md"),
|
||||
meta: { title: "标签" },
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
|
Loading…
Reference in New Issue
Block a user