Commit 60577d6720fd3f8d4d1a88b20ab902d6161a0eec
1 parent
953bfc6f
feat(tree): add searchable function
添加搜索功能相关属性和方法 close: #1057
Showing
5 changed files
with
51 additions
and
7 deletions
CHANGELOG.zh_CN.md
src/components/Tree/src/Tree.vue
@@ -42,7 +42,14 @@ | @@ -42,7 +42,14 @@ | ||
42 | name: 'BasicTree', | 42 | name: 'BasicTree', |
43 | inheritAttrs: false, | 43 | inheritAttrs: false, |
44 | props: basicProps, | 44 | props: basicProps, |
45 | - emits: ['update:expandedKeys', 'update:selectedKeys', 'update:value', 'change', 'check'], | 45 | + emits: [ |
46 | + 'update:expandedKeys', | ||
47 | + 'update:selectedKeys', | ||
48 | + 'update:value', | ||
49 | + 'change', | ||
50 | + 'check', | ||
51 | + 'update:searchValue', | ||
52 | + ], | ||
46 | setup(props, { attrs, slots, emit, expose }) { | 53 | setup(props, { attrs, slots, emit, expose }) { |
47 | const state = reactive<State>({ | 54 | const state = reactive<State>({ |
48 | checkStrictly: props.checkStrictly, | 55 | checkStrictly: props.checkStrictly, |
@@ -192,7 +199,14 @@ | @@ -192,7 +199,14 @@ | ||
192 | state.checkStrictly = strictly; | 199 | state.checkStrictly = strictly; |
193 | } | 200 | } |
194 | 201 | ||
202 | + const searchText = ref(''); | ||
203 | + watchEffect(() => { | ||
204 | + if (props.searchValue !== searchText.value) searchText.value = props.searchValue; | ||
205 | + }); | ||
206 | + | ||
195 | function handleSearch(searchValue: string) { | 207 | function handleSearch(searchValue: string) { |
208 | + if (searchValue !== searchText.value) searchText.value = searchValue; | ||
209 | + emit('update:searchValue', searchValue); | ||
196 | if (!searchValue) { | 210 | if (!searchValue) { |
197 | searchState.startSearch = false; | 211 | searchState.startSearch = false; |
198 | return; | 212 | return; |
@@ -293,6 +307,12 @@ | @@ -293,6 +307,12 @@ | ||
293 | filterByLevel: (level: number) => { | 307 | filterByLevel: (level: number) => { |
294 | state.expandedKeys = filterByLevel(level); | 308 | state.expandedKeys = filterByLevel(level); |
295 | }, | 309 | }, |
310 | + setSearchValue: (value: string) => { | ||
311 | + handleSearch(value); | ||
312 | + }, | ||
313 | + getSearchValue: () => { | ||
314 | + return searchText.value; | ||
315 | + }, | ||
296 | }; | 316 | }; |
297 | 317 | ||
298 | expose(instance); | 318 | expose(instance); |
@@ -380,6 +400,7 @@ | @@ -380,6 +400,7 @@ | ||
380 | helpMessage={helpMessage} | 400 | helpMessage={helpMessage} |
381 | onStrictlyChange={onStrictlyChange} | 401 | onStrictlyChange={onStrictlyChange} |
382 | onSearch={handleSearch} | 402 | onSearch={handleSearch} |
403 | + searchText={unref(searchText)} | ||
383 | > | 404 | > |
384 | {extendSlots(slots)} | 405 | {extendSlots(slots)} |
385 | </TreeHeader> | 406 | </TreeHeader> |
src/components/Tree/src/TreeHeader.vue
@@ -11,7 +11,7 @@ | @@ -11,7 +11,7 @@ | ||
11 | :placeholder="t('common.searchText')" | 11 | :placeholder="t('common.searchText')" |
12 | size="small" | 12 | size="small" |
13 | allowClear | 13 | allowClear |
14 | - @change="handleSearch" | 14 | + v-model:value="searchValue" |
15 | /> | 15 | /> |
16 | </div> | 16 | </div> |
17 | <Dropdown @click.prevent v-if="toolbar"> | 17 | <Dropdown @click.prevent v-if="toolbar"> |
@@ -32,7 +32,7 @@ | @@ -32,7 +32,7 @@ | ||
32 | </template> | 32 | </template> |
33 | <script lang="ts"> | 33 | <script lang="ts"> |
34 | import type { PropType } from 'vue'; | 34 | import type { PropType } from 'vue'; |
35 | - import { defineComponent, computed } from 'vue'; | 35 | + import { defineComponent, computed, ref, watch } from 'vue'; |
36 | 36 | ||
37 | import { Dropdown, Menu, Input } from 'ant-design-vue'; | 37 | import { Dropdown, Menu, Input } from 'ant-design-vue'; |
38 | import { Icon } from '/@/components/Icon'; | 38 | import { Icon } from '/@/components/Icon'; |
@@ -77,10 +77,12 @@ | @@ -77,10 +77,12 @@ | ||
77 | search: propTypes.bool, | 77 | search: propTypes.bool, |
78 | checkAll: propTypes.func, | 78 | checkAll: propTypes.func, |
79 | expandAll: propTypes.func, | 79 | expandAll: propTypes.func, |
80 | + searchText: propTypes.string, | ||
80 | }, | 81 | }, |
81 | emits: ['strictly-change', 'search'], | 82 | emits: ['strictly-change', 'search'], |
82 | setup(props, { emit }) { | 83 | setup(props, { emit }) { |
83 | const { t } = useI18n(); | 84 | const { t } = useI18n(); |
85 | + const searchValue = ref(''); | ||
84 | 86 | ||
85 | const toolbarList = computed(() => { | 87 | const toolbarList = computed(() => { |
86 | const { checkable } = props; | 88 | const { checkable } = props; |
@@ -137,11 +139,25 @@ | @@ -137,11 +139,25 @@ | ||
137 | } | 139 | } |
138 | const debounceEmitChange = useDebounceFn(emitChange, 200); | 140 | const debounceEmitChange = useDebounceFn(emitChange, 200); |
139 | 141 | ||
140 | - function handleSearch(e: ChangeEvent): void { | ||
141 | - debounceEmitChange(e.target.value); | ||
142 | - } | 142 | + watch( |
143 | + () => searchValue.value, | ||
144 | + (v) => { | ||
145 | + debounceEmitChange(v); | ||
146 | + } | ||
147 | + ); | ||
148 | + watch( | ||
149 | + () => props.searchText, | ||
150 | + (v) => { | ||
151 | + if (v !== searchValue.value) { | ||
152 | + searchValue.value = v; | ||
153 | + } | ||
154 | + } | ||
155 | + ); | ||
156 | + // function handleSearch(e: ChangeEvent): void { | ||
157 | + // debounceEmitChange(e.target.value); | ||
158 | + // } | ||
143 | 159 | ||
144 | - return { t, toolbarList, handleMenuClick, handleSearch }; | 160 | + return { t, toolbarList, handleMenuClick, searchValue }; |
145 | }, | 161 | }, |
146 | }); | 162 | }); |
147 | </script> | 163 | </script> |
src/components/Tree/src/props.ts
@@ -20,6 +20,7 @@ export const basicProps = { | @@ -20,6 +20,7 @@ export const basicProps = { | ||
20 | title: propTypes.string, | 20 | title: propTypes.string, |
21 | toolbar: propTypes.bool, | 21 | toolbar: propTypes.bool, |
22 | search: propTypes.bool, | 22 | search: propTypes.bool, |
23 | + searchValue: propTypes.string, | ||
23 | checkStrictly: propTypes.bool, | 24 | checkStrictly: propTypes.bool, |
24 | clickRowToExpand: propTypes.bool.def(true), | 25 | clickRowToExpand: propTypes.bool.def(true), |
25 | checkable: propTypes.bool.def(false), | 26 | checkable: propTypes.bool.def(false), |
src/components/Tree/src/typing.ts
@@ -34,6 +34,8 @@ export interface TreeActionType { | @@ -34,6 +34,8 @@ export interface TreeActionType { | ||
34 | insertNodesByKey: (opt: InsertNodeParams) => void; | 34 | insertNodesByKey: (opt: InsertNodeParams) => void; |
35 | deleteNodeByKey: (key: string) => void; | 35 | deleteNodeByKey: (key: string) => void; |
36 | updateNodeByKey: (key: string, node: Omit<TreeDataItem, 'key'>) => void; | 36 | updateNodeByKey: (key: string, node: Omit<TreeDataItem, 'key'>) => void; |
37 | + setSearchValue: (value: string) => void; | ||
38 | + getSearchValue: () => string; | ||
37 | } | 39 | } |
38 | 40 | ||
39 | export interface InsertNodeParams { | 41 | export interface InsertNodeParams { |