Commit 60577d6720fd3f8d4d1a88b20ab902d6161a0eec

Authored by 无木
1 parent 953bfc6f

feat(tree): add searchable function

添加搜索功能相关属性和方法

close: #1057
CHANGELOG.zh_CN.md
  1 +### ✨ Features
  2 +
  3 +- **BasicTree** 添加搜索功能相关属性和方法
  4 +
1 ### 🐛 Bug Fixes 5 ### 🐛 Bug Fixes
2 6
3 - **Cropper** 修复未能及时销毁的问题 7 - **Cropper** 修复未能及时销毁的问题
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 {