perf: flatten children
parent
dd68c0d314
commit
7eeee692e7
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 = <input id={attrs.id} autoComplete="off" />;
|
||||
const defaultInput = <input {...(attrs.id !== undefined ? {id: attrs.id}: {})} autoComplete="off"/>;
|
||||
|
||||
const inputElement = props.getInputElement ? props.getInputElement() : defaultInput;
|
||||
const inputCls = classnames(inputElement.class, {
|
||||
|
@ -795,7 +796,6 @@ const Select = {
|
|||
<div class={`${props.prefixCls}-search__field__wrap`} onClick={this.inputClick}>
|
||||
{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 (
|
||||
<MenuItem key={childValueSub} value={childValueSub} {...subChild.props}>
|
||||
{...(subChild.children?.default())}
|
||||
{...getSlot(subChild)}
|
||||
</MenuItem>
|
||||
);
|
||||
});
|
||||
|
@ -1247,7 +1262,7 @@ const Select = {
|
|||
style: UNSELECTABLE_STYLE,
|
||||
class: child?.class,
|
||||
};
|
||||
const menuItem = <MenuItem {...p}>{child.children?.default()}</MenuItem>;
|
||||
const menuItem = <MenuItem {...p}>{getSlot(child)}</MenuItem>;
|
||||
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)) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue