Skip to content

refactor: search #240

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Mar 15, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 25 additions & 30 deletions packages/devui-vue/devui/search/src/hooks/use-search-keydown.ts
Original file line number Diff line number Diff line change
@@ -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<string>, delay: number): KeydownReturnTypes => {
// 删除按钮显示
const onInputKeydown = ($event: KeyboardEvent) => {
switch ($event.key) {
case KEYS_MAP.enter:
handleEnter($event)
break
default:
break
}
}
export const keydownHandles = (ctx: SetupContext<EmitProps[]>, keywords: Ref<string>, 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
}
}

onClickHandle,
};
};
39 changes: 19 additions & 20 deletions packages/devui-vue/devui/search/src/hooks/use-search-keywords.ts
Original file line number Diff line number Diff line change
@@ -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<EmitProps[]>, 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,
};
};
42 changes: 19 additions & 23 deletions packages/devui-vue/devui/search/src/search-types.ts
Original file line number Diff line number Diff line change
@@ -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: {
Expand All @@ -10,7 +10,7 @@ export const searchProps = {
},
placeholder: {
type: String,
default: '请输入关键字'
default: '请输入关键字',
},
maxLength: {
type: Number,
Expand All @@ -22,52 +22,48 @@ 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<IconPosition>,
default: 'right',
},
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<typeof searchProps>
export type SearchProps = ExtractPropTypes<typeof searchProps>;

export interface KeywordsReturnTypes {
keywords: Ref<string>
clearIconShow: ComputedRef<boolean>
onClearHandle: () => void
keywords: Ref<string>;
clearIconShow: ComputedRef<boolean>;
onClearHandle: () => void;
}

export interface KeydownReturnTypes {
onInputKeydown: (e: KeyboardEvent) => void
onClickHandle: () => void
useEmitKeyword: (e: string) => void
}
onInputKeydown: (e: KeyboardEvent) => void;
onClickHandle: () => void;
useEmitKeyword: (e: string) => void;
}
74 changes: 33 additions & 41 deletions packages/devui-vue/devui/search/src/search.tsx
Original file line number Diff line number Diff line change
@@ -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 (
<div class={rootClasses.value}>
{props.iconPosition === 'left' &&
<div class="devui-search__icon" onClick={onClickHandle}>
<d-icon name="search" size="inherit" key="search"></d-icon>
{props.iconPosition === 'left' && (
<div class='devui-search__icon' onClick={onClickHandle}>
<d-icon name='search' size='inherit' key='search'></d-icon>
</div>
}
)}
<DInput
size={props.size}
disabled={props.disabled}
Expand All @@ -44,23 +40,19 @@ export default defineComponent({
placeholder={props.placeholder}
cssClass={props.cssClass}
onKeydown={onInputKeydown}
onUpdate:modelValue={onInputUpdate}
></DInput>
{clearIconShow.value &&
<div
class="devui-search__clear"
onClick={onClearHandle}
>
<d-icon name="close" size="inherit" key="close"></d-icon>
</div>
}
{props.iconPosition === 'right' &&
<div class="devui-search__icon" onClick={onClickHandle}>
<d-icon name="search" size="inherit" key="search"></d-icon>
</div>
}
onUpdate:modelValue={onInputUpdate}></DInput>
{clearIconShow.value && (
<div class='devui-search__clear' onClick={onClearHandle}>
<d-icon name='close' size='inherit' key='close'></d-icon>
</div>
)}
{props.iconPosition === 'right' && (
<div class='devui-search__icon' onClick={onClickHandle}>
<d-icon name='search' size='inherit' key='search'></d-icon>
</div>
)}
</div>
)
}
}
})
);
};
},
});
Loading