diff --git a/packages/devui-vue/devui/search/src/hooks/use-search-keydown.ts b/packages/devui-vue/devui/search/src/hooks/use-search-keydown.ts index fab596c393..220f65693e 100644 --- a/packages/devui-vue/devui/search/src/hooks/use-search-keydown.ts +++ b/packages/devui-vue/devui/search/src/hooks/use-search-keydown.ts @@ -1,42 +1,37 @@ /** * 清空按钮显示、隐藏 */ -import { SetupContext, Ref, } from 'vue' -import { KeydownReturnTypes } from '../search-types' -import { debounce } from 'lodash' -const KEYS_MAP = { - enter: 'Enter' -} as const +import { SetupContext, Ref } from 'vue'; +import { KeydownReturnTypes, SearchProps } from '../search-types'; +import { debounce } from 'lodash'; -type EmitProps = 'update:modelValue' | 'onSearch' +type EmitProps = 'update:modelValue' | 'search'; -export const keydownHandles = (ctx: SetupContext<(EmitProps)[]>, keywords: Ref, delay: number): KeydownReturnTypes => { - // 删除按钮显示 - const onInputKeydown = ($event: KeyboardEvent) => { - switch ($event.key) { - case KEYS_MAP.enter: - handleEnter($event) - break - default: - break - } - } +export const keydownHandles = (ctx: SetupContext, keywords: Ref, props: SearchProps): KeydownReturnTypes => { + const useEmitKeyword = debounce((value: string) => { + ctx.emit('search', value); + }, props.delay); const handleEnter = ($event: KeyboardEvent) => { if ($event.target instanceof HTMLInputElement) { - const value = $event.target.value - useEmitKeyword(value) + const value = $event.target.value; + useEmitKeyword(value); } - } + }; const onClickHandle = () => { - useEmitKeyword(keywords.value) - } - const useEmitKeyword = debounce((value: string) => { - ctx.emit('onSearch', value) - }, delay) + if (!props.disabled) { + ctx.emit('search', keywords.value); + } + }; + const KEYS_MAP: { [key: string]: ($event: KeyboardEvent) => void } = { + Enter: handleEnter, + }; + const onInputKeydown = ($event: KeyboardEvent) => { + KEYS_MAP[$event.key]?.($event); + }; + return { onInputKeydown, useEmitKeyword, - onClickHandle - } -} - \ No newline at end of file + onClickHandle, + }; +}; diff --git a/packages/devui-vue/devui/search/src/hooks/use-search-keywords.ts b/packages/devui-vue/devui/search/src/hooks/use-search-keywords.ts index e03864603d..be507da2f4 100644 --- a/packages/devui-vue/devui/search/src/hooks/use-search-keywords.ts +++ b/packages/devui-vue/devui/search/src/hooks/use-search-keywords.ts @@ -1,28 +1,27 @@ /** * 输入框内容定义、删改操作 */ -import { ref, watch, computed, SetupContext } from 'vue' -import { SearchProps, KeywordsReturnTypes } from '../search-types' -type EmitProps = 'update:modelValue' | 'onSearch' +import { ref, watch, computed, SetupContext } from 'vue'; +import { SearchProps, KeywordsReturnTypes } from '../search-types'; +type EmitProps = 'update:modelValue' | 'search'; -export const keywordsHandles = (ctx: SetupContext<(EmitProps)[]>, props: SearchProps): KeywordsReturnTypes => { - const keywords = ref('') // 输入框内容 - // 监听是否有双向绑定,将绑定的值传递给keyword,因为需要清除输入框 - watch(() => props.modelValue, (val)=> { - keywords.value = val - }, { immediate: true }) - // 清空输入框 +export const keywordsHandles = (ctx: SetupContext, props: SearchProps): KeywordsReturnTypes => { + const keywords = ref(''); + watch( + () => props.modelValue, + (val) => { + keywords.value = val; + }, + { immediate: true } + ); const onClearHandle = () => { - keywords.value = '' - // 清空输入框时更新modelValue为空 - ctx.emit('update:modelValue', '') - } - const clearIconShow = computed(() => { - return keywords.value.length > 0 - }) + keywords.value = ''; + ctx.emit('update:modelValue', ''); + }; + const clearIconShow = computed(() => keywords.value.length > 0); return { keywords, clearIconShow, - onClearHandle - } -} + onClearHandle, + }; +}; diff --git a/packages/devui-vue/devui/search/src/search-types.ts b/packages/devui-vue/devui/search/src/search-types.ts index 23c74e20a0..cd26817f9e 100644 --- a/packages/devui-vue/devui/search/src/search-types.ts +++ b/packages/devui-vue/devui/search/src/search-types.ts @@ -1,7 +1,7 @@ -import type { PropType, ExtractPropTypes, Ref, ComputedRef } from 'vue' +import type { PropType, ExtractPropTypes, Ref, ComputedRef } from 'vue'; -export type Size = 'lg' | 'sm' | '' -export type IconPosition = 'right' | 'left' +export type Size = 'lg' | 'sm' | ''; +export type IconPosition = 'right' | 'left'; export const searchProps = { size: { @@ -10,7 +10,7 @@ export const searchProps = { }, placeholder: { type: String, - default: '请输入关键字' + default: '请输入关键字', }, maxLength: { type: Number, @@ -22,15 +22,15 @@ export const searchProps = { }, disabled: { type: Boolean, - default: false + default: false, }, autoFocus: { type: Boolean, - default: false + default: false, }, isKeyupSearch: { type: Boolean, - default: false + default: false, }, iconPosition: { type: String as PropType, @@ -38,36 +38,32 @@ export const searchProps = { }, noBorder: { type: Boolean, - default: false + default: false, }, cssClass: { type: String, - default: '' + default: '', }, modelValue: { type: String, default: '', }, - onSearch: { - type: Function as PropType<(v: string) => void>, - default: undefined - }, 'onUpdate:modelValue': { type: Function as PropType<(v: string) => void>, - default: undefined + default: undefined, }, -} as const +} as const; -export type SearchProps = ExtractPropTypes +export type SearchProps = ExtractPropTypes; export interface KeywordsReturnTypes { - keywords: Ref - clearIconShow: ComputedRef - onClearHandle: () => void + keywords: Ref; + clearIconShow: ComputedRef; + onClearHandle: () => void; } export interface KeydownReturnTypes { - onInputKeydown: (e: KeyboardEvent) => void - onClickHandle: () => void - useEmitKeyword: (e: string) => void -} \ No newline at end of file + onInputKeydown: (e: KeyboardEvent) => void; + onClickHandle: () => void; + useEmitKeyword: (e: string) => void; +} diff --git a/packages/devui-vue/devui/search/src/search.tsx b/packages/devui-vue/devui/search/src/search.tsx index 004a106ac5..ef4bef2bfe 100644 --- a/packages/devui-vue/devui/search/src/search.tsx +++ b/packages/devui-vue/devui/search/src/search.tsx @@ -1,40 +1,36 @@ -import { defineComponent } from 'vue' -import { SearchProps, searchProps } from './search-types' -import { getRootClass } from './hooks/use-search-class' -import { keywordsHandles } from './hooks/use-search-keywords' -import { keydownHandles } from './hooks/use-search-keydown' +import { defineComponent } from 'vue'; +import { SearchProps, searchProps } from './search-types'; +import { getRootClass } from './hooks/use-search-class'; +import { keywordsHandles } from './hooks/use-search-keywords'; +import { keydownHandles } from './hooks/use-search-keydown'; import DInput from '../../input/src/input'; -import './search.scss' +import './search.scss'; export default defineComponent({ name: 'DSearch', props: searchProps, - emits: ['update:modelValue', 'onSearch'], + emits: ['update:modelValue', 'search'], setup(props: SearchProps, ctx) { - const rootClasses = getRootClass(props) - // 输入框内容定义、删改 - const {keywords, clearIconShow, onClearHandle} = keywordsHandles(ctx, props) + const rootClasses = getRootClass(props); + const { keywords, clearIconShow, onClearHandle } = keywordsHandles(ctx, props); + const { onInputKeydown, onClickHandle, useEmitKeyword } = keydownHandles(ctx, keywords, props); - // 键盘回车事件 - const { onInputKeydown, onClickHandle, useEmitKeyword } = keydownHandles(ctx, keywords, props.delay) - - // 双向绑定 const onInputUpdate = (event: string) => { if (props.isKeyupSearch) { - useEmitKeyword(event) + useEmitKeyword(event); } - keywords.value = event - ctx.emit('update:modelValue', event) - } + keywords.value = event; + ctx.emit('update:modelValue', event); + }; return () => { return (
- {props.iconPosition === 'left' && -
- + {props.iconPosition === 'left' && ( +
+
- } + )} - {clearIconShow.value && -
- -
- } - {props.iconPosition === 'right' && -
- -
- } + onUpdate:modelValue={onInputUpdate}> + {clearIconShow.value && ( +
+ +
+ )} + {props.iconPosition === 'right' && ( +
+ +
+ )}
- ) - } - } -}) \ No newline at end of file + ); + }; + }, +}); diff --git a/packages/devui-vue/docs/components/search/index.md b/packages/devui-vue/docs/components/search/index.md index b1127a8fa0..5db0837a1d 100644 --- a/packages/devui-vue/docs/components/search/index.md +++ b/packages/devui-vue/docs/components/search/index.md @@ -2,7 +2,7 @@ 搜索框。 -### 何时使用 +#### 何时使用 当用户需要在数据集中搜索所需数据时,输入所需数据的内容(或部分内容),返回所有匹配内容的搜索结果。 @@ -12,36 +12,32 @@ ```vue ``` + ::: ### 搜索图标左置 @@ -51,23 +47,25 @@ export default defineComponent({ ```vue ``` + ::: ### 无边框 -:::demo 使用`noBorder`来定义`Search`无边框 +:::demo 使用`no-border`来定义`Search`无边框 ```vue ``` + ::: ### 双向绑定 @@ -75,57 +73,43 @@ export default defineComponent({ :::demo 使用`v-model`双向绑定 ```vue - ``` ::: -### API - -| 参数 | 类型 | 默认 | 说明 | 跳转 Demo | 全局配置项 | -| :---------: | :------: | :-------: | :----------------------- | --------------------------------- | --------- | -| size | `'sm'\|''\|'lg'` | '' | 可选,搜索框尺寸,有三种选择 lg、''、sm | [基本用法](#基本用法) || -| placeholder | `string` | -- | 可选,输入框 placeholder | [搜索图标左置](#搜索图标左置) || -| maxLength | `number` | -- | 可选,输入框的 max-length | [双向绑定](#双向绑定) || -| delay | `number` | 300 | 可选,debounceTime 的延迟 | [基本用法](#基本用法) || -| disabled | `boolean` | false | 可选,输入框是否被禁用 | [基本用法](#基本用法) || -| autoFocus | `boolean` | false | 可选,输入框是否自动对焦 | [基本用法](#基本用法) || -| isKeyupSearch | `boolean` | false | 可选,是否支持输入值立即触发 onSearch | [基本用法](#基本用法) || -| iconPosition | `string` | 'right' | 可选,搜索图标位置,有两种选择'left' / 'right' | [搜索图标左置](#搜索图标左置) || -| noBorder | `boolean` | false | 可选,是否显示边框 | [无边框](#无边框) || -| cssClass | `string` | '' | 可选,支持传入类名到输入框上 | [双向绑定](#双向绑定) || +### d-search 参数 + +| 参数 | 类型 | 默认 | 说明 | 跳转 Demo | 全局配置项 | +| --------------- | :--------------- | ------- | ---------------------------------------------- | ----------------------------- | ---------- | +| size | `'sm'\|''\|'lg'` | '' | 可选,搜索框尺寸,有三种选择 lg、''、sm | [基本用法](#基本用法) | | +| placeholder | `string` | -- | 可选,输入框 placeholder | [搜索图标左置](#搜索图标左置) | | +| max-length | `number` | -- | 可选,输入框的 max-length | [双向绑定](#双向绑定) | | +| delay | `number` | 300 | 可选,debounceTime 的延迟 | [基本用法](#基本用法) | | +| disabled | `boolean` | false | 可选,输入框是否被禁用 | [基本用法](#基本用法) | | +| auto-focus | `boolean` | false | 可选,输入框是否自动对焦 | [基本用法](#基本用法) | | +| is-keyup-search | `boolean` | false | 可选,是否支持输入值立即触发 `search` | [基本用法](#基本用法) | | +| icon-position | `string` | 'right' | 可选,搜索图标位置,有两种选择'left' / 'right' | [搜索图标左置](#搜索图标左置) | | +| no-border | `boolean` | false | 可选,是否显示边框 | [无边框](#无边框) | | +| css-class | `string` | '' | 可选,支持传入类名到输入框上 | [双向绑定](#双向绑定) | | ### d-search 事件 -| 事件 | 类型 | 说明 | 跳转 Demo | -| :---------: | :------: | :--------------------: | :---------: | -| onSearch | `string` | 回车或点击搜索按钮触发的回调函数,返回文本框输入的值 | [基本用法](#基本用法) | - - \ No newline at end of file +| 事件 | 类型 | 说明 | 跳转 Demo | +| ------ | -------- | ---------------------------------------------------- | --------------------- | +| search | `string` | 回车或点击搜索按钮触发的回调函数,返回文本框输入的值 | [基本用法](#基本用法) |