diff --git a/packages/pro/search/src/components/SearchItem.tsx b/packages/pro/search/src/components/SearchItem.tsx index 23697fcc4..56dbcf37d 100644 --- a/packages/pro/search/src/components/SearchItem.tsx +++ b/packages/pro/search/src/components/SearchItem.tsx @@ -32,7 +32,7 @@ export default defineComponent({ segmentsRef.value?.scrollTo(0, 0) }) - const segmentStateContext = useSegmentStates(props, proSearchProps, context, isActive) + const segmentStateContext = useSegmentStates(props, proSearchProps, context) const segmentOverlayUpdateContext = useSegmentOverlayUpdate() const { searchState, segmentStates } = segmentStateContext diff --git a/packages/pro/search/src/composables/useSearchStates.ts b/packages/pro/search/src/composables/useSearchStates.ts index d4b5cef8c..145259a53 100644 --- a/packages/pro/search/src/composables/useSearchStates.ts +++ b/packages/pro/search/src/composables/useSearchStates.ts @@ -49,6 +49,7 @@ export function useSearchStates( const { searchValues, setSearchValues } = searchValueContext const getKey = createStateKeyGetter() const { isMarked, getMarks, mark, unmark, clearMarks } = useSearchStateMarks() + let queuedUpdateCnt = 0 const searchStates = ref([]) const searchStateKeyMap = computed(() => { @@ -294,7 +295,7 @@ export function useSearchStates( return newSearchState } - function updateSearchValues() { + function _updateSearchValues() { const newSearchValues = searchStates.value .map(state => { // filters invalid searchValues @@ -318,6 +319,29 @@ export function useSearchStates( callEmit(props.onChange, toRaw(newSearchValues), toRaw(oldeSearchValue)) } } + function updateSearchValues() { + queuedUpdateCnt++ + + if (queuedUpdateCnt > 1) { + return + } + + const exec = () => { + _updateSearchValues() + + // queue update operation until next macro task loop + // to prevent repeated updates + setTimeout(() => { + queuedUpdateCnt-- + + if (queuedUpdateCnt > 0) { + exec() + } + }) + } + + exec() + } const updateSegmentValue = (key: VKey, name: string, value: unknown) => { if (props.disabled) { diff --git a/packages/pro/search/src/composables/useSegmentStates.ts b/packages/pro/search/src/composables/useSegmentStates.ts index e5b1f11f7..c649eae5b 100644 --- a/packages/pro/search/src/composables/useSegmentStates.ts +++ b/packages/pro/search/src/composables/useSegmentStates.ts @@ -39,7 +39,6 @@ export function useSegmentStates( props: SearchItemProps, proSearchProps: ProSearchProps, proSearchContext: ProSearchContext, - isActive: ComputedRef, ): SegmentStatesContext { const { initSearchState, @@ -173,11 +172,35 @@ export function useSegmentStates( } } - watch([isActive, () => props.searchItem?.resolvedSearchField], ([active, searchField]) => { - if (!active || !searchField) { - initSearchState(props.searchItem!.key) - } - }) + watch( + [activeSegment, () => props.searchItem?.resolvedSearchField], + ([activeSegment, searchField], [preActiveSegment]) => { + if (activeSegment?.itemKey === props.searchItem?.key) { + return + } + + if (!searchField) { + initSearchState(props.searchItem!.key) + return + } + + const preSegment = props.searchItem?.resolvedSearchField.segments.find(seg => seg.name === preActiveSegment?.name) + + // if current segment has no panel and the whole search item is valid after input + // then update search values + // + // we do this to improve user experience + // because always pressing `Enter` after input to trigger update could be annoying + if (preSegment && !preSegment.panelRenderer && validateSearchState(props.searchItem!.key)) { + updateSearchValues() + } else { + initSearchState(props.searchItem!.key) + } + }, + { + flush: 'post', + }, + ) return { searchState,