diff --git a/components/_util/props-util.js b/components/_util/props-util.js index efcc81c5d..930f8a3de 100644 --- a/components/_util/props-util.js +++ b/components/_util/props-util.js @@ -67,12 +67,39 @@ const getSlots = ele => { }); return { ...slots, ...getScopedSlots(ele) }; }; + +const flattenChildren = (children = [], filterEmpty = true) => { + const temp = Array.isArray(children) ? children : [children]; + const res = []; + temp.forEach(child => { + if (Array.isArray(child)) { + res.push(...flattenChildren(child, filterEmpty)); + } else if (child && child.type === Fragment) { + res.push(...flattenChildren(child.children, filterEmpty)); + } else if (child && isVNode(child)) { + if (filterEmpty && !isEmptyElement(child)) { + res.push(child); + } else if (!filterEmpty) { + res.push(child); + } + } + }); + return res; +}; + const getSlot = (self, name = 'default', options = {}) => { - let res = self.$slots[name] && self.$slots[name](options); - while (res && res.length === 1 && (res[0].type === Fragment || Array.isArray(res[0]))) { - res = res[0].children || res[0]; + if (isVNode(self)) { + if (self.type === Fragment) { + return name === 'default' ? flattenChildren(self.children) : []; + } else if (self.children && self.children[name]) { + return flattenChildren(self.children[name](options)); + } else { + return []; + } + } else { + let res = self.$slots[name] && self.$slots[name](options); + return flattenChildren(res); } - return res && res.__v_isVNode ? [res] : res; }; const getAllChildren = ele => { @@ -128,26 +155,32 @@ const getOptionProps = instance => { return res; }; const getComponent = (instance, prop = 'default', options = instance, execute = true) => { + let com = undefined; if (instance.$) { const temp = instance[prop]; if (temp !== undefined) { return typeof temp === 'function' && execute ? temp(options) : temp; } else { - let com = instance.$slots[prop]; + com = instance.$slots[prop]; com = execute && com ? com(options) : com; - return Array.isArray(com) && com.length === 1 ? com[0] : com; } } else if (isVNode(instance)) { const temp = instance.props && instance.props[prop]; - if (temp !== undefined && temp !== null) { + if (temp !== undefined && instance.props !== null) { return typeof temp === 'function' && execute ? temp(options) : temp; + } else if (instance.type === Fragment) { + com = instance.children; } else if (instance.children && instance.children[prop]) { - let com = instance.children[prop]; + com = instance.children[prop]; com = execute && com ? com(options) : com; - return Array.isArray(com) && com.length === 1 ? com[0] : com; } } - return undefined; + if (Array.isArray(com)) { + com = flattenChildren(com); + com = com.length === 1 ? com[0] : com; + com = com.length === 0 ? undefined : com; + } + return com; }; const getComponentFromProp = (instance, prop, options = instance, execute = true) => { if (instance.$createElement) { @@ -381,5 +414,6 @@ export { getAllProps, getAllChildren, findDOMNode, + flattenChildren, }; export default hasProp; diff --git a/components/vc-select/DropdownMenu.jsx b/components/vc-select/DropdownMenu.jsx index 3d86a8fe9..178b53e76 100644 --- a/components/vc-select/DropdownMenu.jsx +++ b/components/vc-select/DropdownMenu.jsx @@ -5,7 +5,7 @@ import scrollIntoView from 'dom-scroll-into-view'; import { getSelectKeys, preventDefaultEvent, saveRef } from './util'; import { cloneElement } from '../_util/vnode'; import BaseMixin from '../_util/BaseMixin'; -import { findDOMNode } from '../_util/props-util'; +import { findDOMNode, getSlot } from '../_util/props-util'; export default { name: 'DropdownMenu', @@ -152,7 +152,7 @@ export default { clonedMenuItems = menuItems.map(item => { if (item.type.isMenuItemGroup) { - const children = (item.children?.default() || []).map(clone); + const children = getSlot(item).map(clone); const newItem = cloneElement(item); newItem.children = { ...item.children, default: () => children }; return newItem; diff --git a/components/vc-select/Select.jsx b/components/vc-select/Select.jsx index 54c6e6632..a5bcd6941 100644 --- a/components/vc-select/Select.jsx +++ b/components/vc-select/Select.jsx @@ -14,6 +14,7 @@ import { getComponent, getEvents, getOptionProps, + getSlot, } from '../_util/props-util'; import getTransitionProps from '../_util/getTransitionProps'; import { cloneElement } from '../_util/vnode'; @@ -223,11 +224,11 @@ const Select = { }, getOptionsFromChildren(children = [], options = []) { children.forEach(child => { - if (!child.data || child.data.slot !== undefined) { + if (!child) { return; } if (child.type?.isSelectOptGroup) { - this.getOptionsFromChildren(child.children?.default(), options); + this.getOptionsFromChildren(getSlot(child), options); } else { options.push(child); } @@ -782,7 +783,7 @@ const Select = { const props = this.$props; const { _inputValue: inputValue, _mirrorInputValue } = this.$data; const attrs = this.$attrs; - const defaultInput = ; + const defaultInput = ; const inputElement = props.getInputElement ? props.getInputElement() : defaultInput; const inputCls = classnames(inputElement.class, { @@ -795,7 +796,6 @@ const Select = {
{cloneElement(inputElement, { disabled: props.disabled, - value: inputValue, ...(inputElement.props || {}), disabled: props.disabled, value: inputValue, @@ -881,6 +881,21 @@ const Select = { if (fireSearch) { this.$emit('search', inputValue); } + } else { + // TODO + // https://github.com/vuejs/vue-next/issues/1471 + this.setState( + { + _inputValue: `${inputValue} `, + }, + ); + this.$nextTick(()=>{ + this.setState( + { + _inputValue: inputValue, + }, + ); + }); } }, getValueByInput(str) { @@ -1200,7 +1215,7 @@ const Select = { const childValueSub = getValuePropValue(subChild) || subChild.key; return ( - {...(subChild.children?.default())} + {...getSlot(subChild)} ); }); @@ -1247,7 +1262,7 @@ const Select = { style: UNSELECTABLE_STYLE, class: child?.class, }; - const menuItem = {child.children?.default()}; + const menuItem = {getSlot(child)}; sel.push(menuItem); menuItems.push(menuItem); } @@ -1503,14 +1518,17 @@ const Select = { } } }, - selectionRefFocus(e) { - if (this._focused || this.disabled || isMultipleOrTagsOrCombobox(this.$props)) { - e.preventDefault(); - return; + selectionRefFocus() { + if (this.getInputDOMNode() && this.getInputDOMNode()) { + this.getInputDOMNode().focus(); } - this._focused = true; - this.updateFocusClassName(); - this.$emit('focus'); + // if (this._focused || this.disabled || isMultipleOrTagsOrCombobox(this.$props)) { + // e.preventDefault(); + // return; + // } + // this._focused = true; + // this.updateFocusClassName(); + // this.$emit('focus'); }, selectionRefBlur(e) { if (isMultipleOrTagsOrCombobox(this.$props)) { diff --git a/components/vc-select/util.js b/components/vc-select/util.js index 18e8813c7..80f06b0f9 100644 --- a/components/vc-select/util.js +++ b/components/vc-select/util.js @@ -1,4 +1,4 @@ -import { getPropsData, getComponent } from '../_util/props-util'; +import { getPropsData, getComponent, getSlot } from '../_util/props-util'; import { cloneElement } from '../_util/vnode'; import { isVNode, Text } from 'vue'; @@ -115,7 +115,7 @@ export function getSelectKeys(menuItems = [], value) { let selectedKeys = []; menuItems.forEach(item => { if (item.type?.isMenuItemGroup) { - selectedKeys = selectedKeys.concat(getSelectKeys(item.children?.default(), value)); + selectedKeys = selectedKeys.concat(getSelectKeys(getSlot(item), value)); } else { const itemValue = getValuePropValue(item); const itemKey = item.key; @@ -141,7 +141,7 @@ export function findFirstMenuItem(children) { const child = children[i]; const props = getPropsData(child); if (child.type?.isMenuItemGroup) { - const found = findFirstMenuItem(child.children?.default()); + const found = findFirstMenuItem(getSlot(child)); if (found) { return found; }