Skip to content

Commit d32dd9f

Browse files
vaebekagol
authored andcommitted
feat(tag-input): v-model:tags 修改为 v-model,更新文档、测试用例
1 parent 40ff12b commit d32dd9f

File tree

4 files changed

+54
-30
lines changed

4 files changed

+54
-30
lines changed

packages/devui-vue/devui/tag-input/__tests__/tag-input.spec.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,24 @@ import { mount } from '@vue/test-utils';
22
import { reactive, nextTick } from 'vue';
33
import DTagInput from '../src/tag-input';
44
import { useNamespace } from '../../shared/hooks/use-namespace';
5+
import { Suggestion } from '../src/tag-input-types';
6+
7+
interface StateType {
8+
tags: Array<Suggestion>;
9+
suggestionList: Array<Suggestion>;
10+
}
511

612
jest.mock('../../locale/create', () => ({
713
createI18nTranslate: () => jest.fn(),
814
}));
915

1016
const ns = useNamespace('tag-input', true);
1117

12-
const customMount = (state) => mount({
18+
const customMount = (state: StateType) => mount({
1319
components: { DTagInput },
1420
template: `
1521
<d-tag-input
16-
v-model:tags="state.tags"
22+
v-model="state.tags"
1723
v-model:suggestionList="state.suggestionList"
1824
displayProperty="cname"
1925
></d-tag-input>
@@ -116,7 +122,7 @@ describe('DTagInput', () => {
116122
]);
117123
const wrapper = mount(DTagInput, {
118124
props: {
119-
tags,
125+
modelValue: tags,
120126
suggestionList,
121127
maxTags: 1,
122128
},

packages/devui-vue/devui/tag-input/src/tag-input-types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ export interface Suggestion {
77
}
88

99
export const tagInputProps = {
10-
tags: {
10+
modelValue: {
1111
type: Array as PropType<Suggestion[]>,
1212
default: (): [] => [],
1313
},

packages/devui-vue/devui/tag-input/src/tag-input.tsx

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,18 @@ export default defineComponent({
2626
ClickOutside,
2727
},
2828
props: tagInputProps,
29-
emits: ['update:tags', 'update:suggestionList', 'change'],
29+
emits: ['update:modelValue', 'update:suggestionList', 'change'],
3030
setup(props: TagInputProps, ctx: SetupContext) {
3131
const app = getCurrentInstance();
3232
const t = createI18nTranslate('DTagInput', app);
3333

3434
const ns = useNamespace('tag-input');
3535

36+
const selectedTags = ref<Array<Suggestion>>([]);
37+
watch(() => props.modelValue, () => {
38+
selectedTags.value = props.modelValue;
39+
}, { immediate: true, deep: true });
40+
3641
const add = (arr: Suggestion[], target: Suggestion) => {
3742
const res = Object.assign({}, target);
3843
delete res.__index;
@@ -96,7 +101,7 @@ export default defineComponent({
96101
if (tagInputVal.value === '' && mergedSuggestions.value.length === 0) {
97102
return false;
98103
}
99-
if (props.tags.findIndex((item) => item[props.displayProperty] === tagInputVal.value) > -1) {
104+
if (selectedTags.value.findIndex((item) => item[props.displayProperty] === tagInputVal.value) > -1) {
100105
tagInputVal.value = '';
101106
return false;
102107
}
@@ -113,20 +118,20 @@ export default defineComponent({
113118
ctx.emit('update:suggestionList', remove(props.suggestionList, target.__index));
114119
}
115120

116-
const newTags = add(props.tags, res);
117-
ctx.emit('change', props.tags, newTags);
118-
ctx.emit('update:tags', newTags);
121+
const newTags = add(selectedTags.value, res);
122+
ctx.emit('change', selectedTags.value, newTags);
123+
ctx.emit('update:modelValue', newTags);
119124
mergedSuggestions.value.length === 0 && (tagInputVal.value = '');
120125
};
121126

122127
const { onInputKeydown } = useInputKeydown(props, handleEnter, onSelectIndexChange);
123128

124129
const removeTag = ($event: Event, tagIdx: number) => {
125130
$event.preventDefault();
126-
ctx.emit('update:suggestionList', add(props.suggestionList, props.tags[tagIdx]));
127-
const newTags = remove(props.tags, tagIdx);
128-
ctx.emit('change', props.tags, newTags);
129-
ctx.emit('update:tags', newTags);
131+
ctx.emit('update:suggestionList', add(props.suggestionList, selectedTags.value[tagIdx]));
132+
const newTags = remove(selectedTags.value, tagIdx);
133+
ctx.emit('change', selectedTags.value, newTags);
134+
ctx.emit('update:modelValue', newTags);
130135

131136
nextTick(() => {
132137
tagInputRef.value?.focus();
@@ -137,14 +142,14 @@ export default defineComponent({
137142
const onSuggestionItemClick = ($event: Event, itemIndex: number) => {
138143
$event.preventDefault();
139144
const target = mergedSuggestions.value[itemIndex];
140-
const newTags = add(props.tags, target);
145+
const newTags = add(selectedTags.value, target);
141146
const newSuggestions = remove(props.suggestionList, target.__index);
142-
ctx.emit('change', props.tags, newTags);
143-
ctx.emit('update:tags', newTags);
147+
ctx.emit('change', selectedTags.value, newTags);
148+
ctx.emit('update:modelValue', newTags);
144149
ctx.emit('update:suggestionList', newSuggestions);
145150
};
146151

147-
const isTagsLimit = computed(() => props.maxTags <= props.tags.length);
152+
const isTagsLimit = computed(() => props.maxTags <= selectedTags.value.length);
148153
const isShowSuggestion = computed(() => {
149154
return !props.disabled && !isTagsLimit.value && isInputBoxFocus.value;
150155
});
@@ -153,7 +158,7 @@ export default defineComponent({
153158
// 已选择 tags 列表
154159
const chosenTags = () => {
155160
return <ul class="devui-tag-list" title={props.disabled ? props.disabledText : ''}>
156-
{props.tags.map((tag, tagIdx) => {
161+
{selectedTags.value.map((tag, tagIdx) => {
157162
return (
158163
<li class="devui-tag-item">
159164
<span>{tag[props.displayProperty]}</span>

packages/devui-vue/docs/components/tag-input/index.md

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,15 @@
1111
:::demo
1212

1313
```vue
14+
1415
<template>
1516
<d-tag-input
16-
v-model:tags="state.tags"
17+
v-model="state.tags"
1718
v-model:suggestionList="state.suggestionList"
1819
displayProperty="name"
1920
placeholder="Add a tag"
2021
no-data="暂无数据"
21-
:minLength='1'
22+
:minLength="1"
2223
:caseSensitivity="true"
2324
@change="changeValue"
2425
@update:tags="changeTags"
@@ -32,7 +33,7 @@ export default defineComponent({
3233
setup() {
3334
const state = reactive({
3435
tags: [{ name: "123" }],
35-
suggestionList: [{ name: "item1" },{ name: "item2" },{ name: "item3" }, { name: "item4" }]
36+
suggestionList: [{ name: "item1" }, { name: "item2" }, { name: "item3" }, { name: "item4" }]
3637
})
3738
const changeTags = (val) => {
3839
console.log(val)
@@ -54,15 +55,18 @@ export default defineComponent({
5455
})
5556
</script>
5657
```
58+
5759
:::
5860

5961
### disabled
62+
6063
:::demo
6164

6265
```vue
66+
6367
<template>
6468
<d-tag-input
65-
v-model:tags="state.tags"
69+
v-model="state.tags"
6670
v-model:suggestionList="state.suggestionList"
6771
:disabled="true"
6872
></d-tag-input>
@@ -74,7 +78,14 @@ export default defineComponent({
7478
setup() {
7579
const state = reactive({
7680
tags: [{ name: "123" }],
77-
suggestionList: [{ name: "item1" }]
81+
suggestionList: [
82+
{ name: "item1" },
83+
{ name: "item2" },
84+
{ name: "item3" },
85+
{ name: "item4" },
86+
{ name: "item5" },
87+
{ name: "item6" }
88+
]
7889
})
7990
8091
return {
@@ -86,13 +97,16 @@ export default defineComponent({
8697
```
8798

8899
:::
100+
89101
### 标签最小长度&最大标签数
102+
90103
:::demo
91104

92105
```vue
106+
93107
<template>
94108
<d-tag-input
95-
v-model:tags="state.tags"
109+
v-model="state.tags"
96110
v-model:suggestionList="state.suggestionList"
97111
:minLength="3"
98112
:maxTags="5"
@@ -120,16 +134,16 @@ export default defineComponent({
120134

121135
### TagInput 参数
122136

123-
| 参数 | 类型 | 默认 | 说明 | 跳转 Demo | 全局配置项 |
124-
| :-------------: | :-------: | :---------------------: | :----------------------------------: | :-------------------- | ---------- |
125-
| tags | `Array` | [] | 必选,记录输入的标签和选择的标签列表 | [基本用法](#基本用法) |
137+
| 参数 | 类型 | 默认 | 说明 | 跳转 Demo | 全局配置项 |
138+
|:---------------:| :-------: | :---------------------: | :----------------------------------: | :-------------------- | ---------- |
139+
| v-model | `Array` | [] | 必选,记录输入的标签和选择的标签列表 | [基本用法](#基本用法) |
126140
| suggestionList | `Array` | [] | 可选,下拉选项,默认可选择的标签列表 | [基本用法](#基本用法) |
127141
| displayProperty | `string` | 'name' | 可选,列表项使用的属性名 | [基本用法](#基本用法) |
128142
| placeholder | `boolean` | '' | 可选,输入框的 placeholder | [基本用法](#基本用法) |
129143
| noData | `boolean` | '' | 可选,无数据提示 | [基本用法](#基本用法) |
130144
| maxTags | `number` | Number.MAX_SAFE_INTEGER | 可选,可输入标签的最大个数 | [标签最小长度&最大标签数](#标签最小长度-最大标签数) |
131-
| minLength | `number` | `3` | 可选,可输入标签的最大个数 | [标签最小长度&最大标签数](#标签最小长度-最大标签数) |
132-
| maxLength | `number` | Number.MAX_SAFE_INTEGER | 可选,可输入标签的最大个数 | [标签最小长度&最大标签数](#标签最小长度-最大标签数) |
145+
| minLength | `number` | `3` | 可选,可输入标签的最大个数 | [标签最小长度&最大标签数](#标签最小长度-最大标签数) |
146+
| maxLength | `number` | Number.MAX_SAFE_INTEGER | 可选,可输入标签的最大个数 | [标签最小长度&最大标签数](#标签最小长度-最大标签数) |
133147
| caseSensitivity | `boolean` | false | 可选,大小写敏感,默认忽略大小写 | | |
134148
| spellcheck | `boolean` | true | 可选,input 输入框是否开启拼写检查的 | | |
135149
| isAddBySpace | `boolean` | true | 可选,是否支持空格键输入标签 | | |
@@ -141,5 +155,4 @@ export default defineComponent({
141155
| 事件 | 说明 | 跳转 Demo |
142156
| :---------: | :------------------------------------------------------- | --------------------- |
143157
| change | 当选中某个选项项后,将会调用此函数,参数为当前选择项的值 | [基本用法](#基本用法) |
144-
| update:tags | 当选项数据发生改变时,返回新的标签列表 | [基本用法](#基本用法) |
145158
| update:suggestionList | 当选项数据发生变化时,返回新的可选择标签列表 | [基本用法](#基本用法) |

0 commit comments

Comments
 (0)