From b5f139a1d601e6342d7cc44cc970d6c51d56eb94 Mon Sep 17 00:00:00 2001 From: chenxi_24 Date: Mon, 15 Nov 2021 18:10:21 +0800 Subject: [PATCH] =?UTF-8?q?feat=20:=20=E5=A2=9E=E5=8A=A0=E6=87=92=E5=8A=A0?= =?UTF-8?q?=E8=BD=BD=E5=AE=8C=E5=96=84=E7=BB=84=E4=BB=B6=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/editable-select-types.ts | 4 + .../editable-select/src/editable-select.tsx | 156 ++++++----- .../docs/components/editable-select/index.md | 250 ++++++++++++------ yarn.lock | 71 +++-- 4 files changed, 293 insertions(+), 188 deletions(-) diff --git a/packages/devui-vue/devui/editable-select/src/editable-select-types.ts b/packages/devui-vue/devui/editable-select/src/editable-select-types.ts index 4da86666..ee9cb2fd 100644 --- a/packages/devui-vue/devui/editable-select/src/editable-select-types.ts +++ b/packages/devui-vue/devui/editable-select/src/editable-select-types.ts @@ -35,6 +35,10 @@ export const editableSelectProps = { loading: { type: Boolean }, + enableLazyLoad: { + type: Boolean, + default: false + }, remoteMethod: { type: Function as PropType<(inputValue: string) => Array> }, diff --git a/packages/devui-vue/devui/editable-select/src/editable-select.tsx b/packages/devui-vue/devui/editable-select/src/editable-select.tsx index 671e6eb9..c6f095bc 100644 --- a/packages/devui-vue/devui/editable-select/src/editable-select.tsx +++ b/packages/devui-vue/devui/editable-select/src/editable-select.tsx @@ -1,58 +1,43 @@ -import { defineComponent, ref, renderSlot, computed, Transition } from "vue" -import { - OptionItem, - editableSelectProps, - EditableSelectProps, -} from "./editable-select-types" -import "./editable-select.scss" -import { Icon } from "../../icon" -import ClickOutside from "../../shared/devui-directive/clickoutside" -import { className } from "./utils" -import { debounce } from "lodash" +import { defineComponent, ref, renderSlot, computed, Transition, watch } from 'vue' +import { OptionItem, editableSelectProps, EditableSelectProps } from './editable-select-types' +import './editable-select.scss' +import { Icon } from '../../icon' +import ClickOutside from '../../shared/devui-directive/clickoutside' +import { className } from './utils' +import { debounce } from 'lodash' export default defineComponent({ - name: "DEditableSelect", + name: 'DEditableSelect', directives: { ClickOutside }, props: editableSelectProps, - emits: ["update:modelValue"], + emits: ['update:modelValue'], setup(props: EditableSelectProps, ctx) { - const inputCls = className( - "devui-form-control devui-dropdown-origin devui-dropdown-origin-open", - { - disabled: props.disabled, - } - ) - - const getLiCls = (item) => { - const { disabledKey } = props - return className("devui-dropdown-item", { - disabled: disabledKey ? !!item[disabledKey] : false, - }) - } - + const dropdownRef = ref(null) const visible = ref(false) - const inputValue = ref("") + const inputValue = ref('') + const activeIndex = ref(0) const query = ref(props.modelValue) const wait = computed(() => (props.remote ? 300 : 0)) const emptyText = computed(() => { const options = filteredOptions.value - if (!props.remote && inputValue.value && options.length === 0) { - return "没有相关记录" + if (!props.remote && options.length === 0) { + return '没有相关记录' } if (options.length === 0) { - return "没有数据" + return '没有数据' } return null }) + const normalizeOptions = computed(() => { let options: OptionItem const { disabledKey } = props - disabledKey ? disabledKey : "disabled" + disabledKey ? disabledKey : 'disabled' return props.options.map((item) => { - if (typeof item !== "object") { + if (typeof item !== 'object') { options = { - name: item, + name: item } return options } @@ -61,9 +46,11 @@ export default defineComponent({ }) const filteredOptions = computed(() => { - const isValidOption = (o: OptionItem): boolean => { + const isValidOption = (o: OptionItem) => { const query = inputValue.value - const containsQueryString = query ? o.name.includes(query) : true + const containsQueryString = query + ? o.name.toLocaleLowerCase().indexOf(query.toLocaleLowerCase()) >= 0 + : true return containsQueryString } return normalizeOptions.value @@ -76,6 +63,12 @@ export default defineComponent({ .filter((item) => item !== null) }) + const findIndex = (o) => { + return normalizeOptions.value.findIndex((item) => { + return item.name === o.name + }) + } + const handleClose = () => { visible.value = false } @@ -84,11 +77,12 @@ export default defineComponent({ visible.value = !visible.value } } - const onInputChange = () => { + + const onInputChange = (val: string) => { if (props.filterMethod) { - props.filterMethod(inputValue.value) + props.filterMethod(val) } else if (props.remote) { - props.remoteMethod(inputValue.value) + props.remoteMethod(val) } } @@ -99,65 +93,83 @@ export default defineComponent({ inputValue.value = value query.value = value if (props.remote) { - debouncedOnInputChange() + debouncedOnInputChange(value) } else { - onInputChange() + onInputChange(value) } } + const selectOptionClick = (e, item) => { const { disabledKey } = props if (disabledKey && item[disabledKey]) { e.stopPropagation() } else { query.value = item.name - ctx.emit("update:modelValue", item.name) + activeIndex.value = findIndex(item) + inputValue.value = '' + ctx.emit('update:modelValue', item.name) } } + + const loadMore = () => { + if (!props.enableLazyLoad) return + const dropdownVal = dropdownRef.value + if (dropdownVal.clientHeight + dropdownVal.scrollTop >= dropdownVal.scrollHeight) { + props.remoteMethod(inputValue.value) + } + } + return () => { + const selectCls = className('devui-form-group devui-has-feedback', { + 'devui-select-open': visible.value + }) + const inputCls = className( + 'devui-form-control devui-dropdown-origin devui-dropdown-origin-open', + { + disabled: props.disabled + } + ) + + const getLiCls = (item, index) => { + const { disabledKey } = props + return className('devui-dropdown-item', { + disabled: disabledKey ? !!item[disabledKey] : false, + selected: activeIndex.value === index + }) + } + return ( -
- -