perf: flatten children
parent
dd68c0d314
commit
7eeee692e7
|
@ -67,12 +67,39 @@ const getSlots = ele => {
|
||||||
});
|
});
|
||||||
return { ...slots, ...getScopedSlots(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 = {}) => {
|
const getSlot = (self, name = 'default', options = {}) => {
|
||||||
let res = self.$slots[name] && self.$slots[name](options);
|
if (isVNode(self)) {
|
||||||
while (res && res.length === 1 && (res[0].type === Fragment || Array.isArray(res[0]))) {
|
if (self.type === Fragment) {
|
||||||
res = res[0].children || res[0];
|
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 => {
|
const getAllChildren = ele => {
|
||||||
|
@ -128,26 +155,32 @@ const getOptionProps = instance => {
|
||||||
return res;
|
return res;
|
||||||
};
|
};
|
||||||
const getComponent = (instance, prop = 'default', options = instance, execute = true) => {
|
const getComponent = (instance, prop = 'default', options = instance, execute = true) => {
|
||||||
|
let com = undefined;
|
||||||
if (instance.$) {
|
if (instance.$) {
|
||||||
const temp = instance[prop];
|
const temp = instance[prop];
|
||||||
if (temp !== undefined) {
|
if (temp !== undefined) {
|
||||||
return typeof temp === 'function' && execute ? temp(options) : temp;
|
return typeof temp === 'function' && execute ? temp(options) : temp;
|
||||||
} else {
|
} else {
|
||||||
let com = instance.$slots[prop];
|
com = instance.$slots[prop];
|
||||||
com = execute && com ? com(options) : com;
|
com = execute && com ? com(options) : com;
|
||||||
return Array.isArray(com) && com.length === 1 ? com[0] : com;
|
|
||||||
}
|
}
|
||||||
} else if (isVNode(instance)) {
|
} else if (isVNode(instance)) {
|
||||||
const temp = instance.props && instance.props[prop];
|
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;
|
return typeof temp === 'function' && execute ? temp(options) : temp;
|
||||||
|
} else if (instance.type === Fragment) {
|
||||||
|
com = instance.children;
|
||||||
} else if (instance.children && instance.children[prop]) {
|
} else if (instance.children && instance.children[prop]) {
|
||||||
let com = instance.children[prop];
|
com = instance.children[prop];
|
||||||
com = execute && com ? com(options) : com;
|
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) => {
|
const getComponentFromProp = (instance, prop, options = instance, execute = true) => {
|
||||||
if (instance.$createElement) {
|
if (instance.$createElement) {
|
||||||
|
@ -381,5 +414,6 @@ export {
|
||||||
getAllProps,
|
getAllProps,
|
||||||
getAllChildren,
|
getAllChildren,
|
||||||
findDOMNode,
|
findDOMNode,
|
||||||
|
flattenChildren,
|
||||||
};
|
};
|
||||||
export default hasProp;
|
export default hasProp;
|
||||||
|
|
|
@ -5,7 +5,7 @@ import scrollIntoView from 'dom-scroll-into-view';
|
||||||
import { getSelectKeys, preventDefaultEvent, saveRef } from './util';
|
import { getSelectKeys, preventDefaultEvent, saveRef } from './util';
|
||||||
import { cloneElement } from '../_util/vnode';
|
import { cloneElement } from '../_util/vnode';
|
||||||
import BaseMixin from '../_util/BaseMixin';
|
import BaseMixin from '../_util/BaseMixin';
|
||||||
import { findDOMNode } from '../_util/props-util';
|
import { findDOMNode, getSlot } from '../_util/props-util';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'DropdownMenu',
|
name: 'DropdownMenu',
|
||||||
|
@ -152,7 +152,7 @@ export default {
|
||||||
|
|
||||||
clonedMenuItems = menuItems.map(item => {
|
clonedMenuItems = menuItems.map(item => {
|
||||||
if (item.type.isMenuItemGroup) {
|
if (item.type.isMenuItemGroup) {
|
||||||
const children = (item.children?.default() || []).map(clone);
|
const children = getSlot(item).map(clone);
|
||||||
const newItem = cloneElement(item);
|
const newItem = cloneElement(item);
|
||||||
newItem.children = { ...item.children, default: () => children };
|
newItem.children = { ...item.children, default: () => children };
|
||||||
return newItem;
|
return newItem;
|
||||||
|
|
|
@ -14,6 +14,7 @@ import {
|
||||||
getComponent,
|
getComponent,
|
||||||
getEvents,
|
getEvents,
|
||||||
getOptionProps,
|
getOptionProps,
|
||||||
|
getSlot,
|
||||||
} from '../_util/props-util';
|
} from '../_util/props-util';
|
||||||
import getTransitionProps from '../_util/getTransitionProps';
|
import getTransitionProps from '../_util/getTransitionProps';
|
||||||
import { cloneElement } from '../_util/vnode';
|
import { cloneElement } from '../_util/vnode';
|
||||||
|
@ -223,11 +224,11 @@ const Select = {
|
||||||
},
|
},
|
||||||
getOptionsFromChildren(children = [], options = []) {
|
getOptionsFromChildren(children = [], options = []) {
|
||||||
children.forEach(child => {
|
children.forEach(child => {
|
||||||
if (!child.data || child.data.slot !== undefined) {
|
if (!child) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (child.type?.isSelectOptGroup) {
|
if (child.type?.isSelectOptGroup) {
|
||||||
this.getOptionsFromChildren(child.children?.default(), options);
|
this.getOptionsFromChildren(getSlot(child), options);
|
||||||
} else {
|
} else {
|
||||||
options.push(child);
|
options.push(child);
|
||||||
}
|
}
|
||||||
|
@ -782,7 +783,7 @@ const Select = {
|
||||||
const props = this.$props;
|
const props = this.$props;
|
||||||
const { _inputValue: inputValue, _mirrorInputValue } = this.$data;
|
const { _inputValue: inputValue, _mirrorInputValue } = this.$data;
|
||||||
const attrs = this.$attrs;
|
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 inputElement = props.getInputElement ? props.getInputElement() : defaultInput;
|
||||||
const inputCls = classnames(inputElement.class, {
|
const inputCls = classnames(inputElement.class, {
|
||||||
|
@ -795,7 +796,6 @@ const Select = {
|
||||||
<div class={`${props.prefixCls}-search__field__wrap`} onClick={this.inputClick}>
|
<div class={`${props.prefixCls}-search__field__wrap`} onClick={this.inputClick}>
|
||||||
{cloneElement(inputElement, {
|
{cloneElement(inputElement, {
|
||||||
disabled: props.disabled,
|
disabled: props.disabled,
|
||||||
value: inputValue,
|
|
||||||
...(inputElement.props || {}),
|
...(inputElement.props || {}),
|
||||||
disabled: props.disabled,
|
disabled: props.disabled,
|
||||||
value: inputValue,
|
value: inputValue,
|
||||||
|
@ -881,6 +881,21 @@ const Select = {
|
||||||
if (fireSearch) {
|
if (fireSearch) {
|
||||||
this.$emit('search', inputValue);
|
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) {
|
getValueByInput(str) {
|
||||||
|
@ -1200,7 +1215,7 @@ const Select = {
|
||||||
const childValueSub = getValuePropValue(subChild) || subChild.key;
|
const childValueSub = getValuePropValue(subChild) || subChild.key;
|
||||||
return (
|
return (
|
||||||
<MenuItem key={childValueSub} value={childValueSub} {...subChild.props}>
|
<MenuItem key={childValueSub} value={childValueSub} {...subChild.props}>
|
||||||
{...(subChild.children?.default())}
|
{...getSlot(subChild)}
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
@ -1247,7 +1262,7 @@ const Select = {
|
||||||
style: UNSELECTABLE_STYLE,
|
style: UNSELECTABLE_STYLE,
|
||||||
class: child?.class,
|
class: child?.class,
|
||||||
};
|
};
|
||||||
const menuItem = <MenuItem {...p}>{child.children?.default()}</MenuItem>;
|
const menuItem = <MenuItem {...p}>{getSlot(child)}</MenuItem>;
|
||||||
sel.push(menuItem);
|
sel.push(menuItem);
|
||||||
menuItems.push(menuItem);
|
menuItems.push(menuItem);
|
||||||
}
|
}
|
||||||
|
@ -1503,14 +1518,17 @@ const Select = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
selectionRefFocus(e) {
|
selectionRefFocus() {
|
||||||
if (this._focused || this.disabled || isMultipleOrTagsOrCombobox(this.$props)) {
|
if (this.getInputDOMNode() && this.getInputDOMNode()) {
|
||||||
e.preventDefault();
|
this.getInputDOMNode().focus();
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
this._focused = true;
|
// if (this._focused || this.disabled || isMultipleOrTagsOrCombobox(this.$props)) {
|
||||||
this.updateFocusClassName();
|
// e.preventDefault();
|
||||||
this.$emit('focus');
|
// return;
|
||||||
|
// }
|
||||||
|
// this._focused = true;
|
||||||
|
// this.updateFocusClassName();
|
||||||
|
// this.$emit('focus');
|
||||||
},
|
},
|
||||||
selectionRefBlur(e) {
|
selectionRefBlur(e) {
|
||||||
if (isMultipleOrTagsOrCombobox(this.$props)) {
|
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 { cloneElement } from '../_util/vnode';
|
||||||
import { isVNode, Text } from 'vue';
|
import { isVNode, Text } from 'vue';
|
||||||
|
|
||||||
|
@ -115,7 +115,7 @@ export function getSelectKeys(menuItems = [], value) {
|
||||||
let selectedKeys = [];
|
let selectedKeys = [];
|
||||||
menuItems.forEach(item => {
|
menuItems.forEach(item => {
|
||||||
if (item.type?.isMenuItemGroup) {
|
if (item.type?.isMenuItemGroup) {
|
||||||
selectedKeys = selectedKeys.concat(getSelectKeys(item.children?.default(), value));
|
selectedKeys = selectedKeys.concat(getSelectKeys(getSlot(item), value));
|
||||||
} else {
|
} else {
|
||||||
const itemValue = getValuePropValue(item);
|
const itemValue = getValuePropValue(item);
|
||||||
const itemKey = item.key;
|
const itemKey = item.key;
|
||||||
|
@ -141,7 +141,7 @@ export function findFirstMenuItem(children) {
|
||||||
const child = children[i];
|
const child = children[i];
|
||||||
const props = getPropsData(child);
|
const props = getPropsData(child);
|
||||||
if (child.type?.isMenuItemGroup) {
|
if (child.type?.isMenuItemGroup) {
|
||||||
const found = findFirstMenuItem(child.children?.default());
|
const found = findFirstMenuItem(getSlot(child));
|
||||||
if (found) {
|
if (found) {
|
||||||
return found;
|
return found;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue