feat: tree-select

pull/2682/head
tangjinzhou 2020-07-18 21:40:26 +08:00
parent b442cc0553
commit 61b5bfa0f6
25 changed files with 264 additions and 397 deletions

@ -1 +1 @@
Subproject commit 1cf8913c4b662bc2bda8ec44734e445ec370cc60 Subproject commit e142c7f8cb2025c14d973691cfb90603e9790d46

View File

@ -93,3 +93,7 @@ v-model -> v-model:activeKey
## List ## List
renderItem(item, index) => renderItem({item, index}) 该用单参数 renderItem(item, index) => renderItem({item, index}) 该用单参数
## TreeSelect
treeData 中 scopedSlots => slots , v-model => v-model:value

View File

@ -112,17 +112,8 @@ const getAllChildren = ele => {
} }
return ele.children || componentOptions.children || []; return ele.children || componentOptions.children || [];
}; };
const getSlotOptions = ele => { const getSlotOptions = () => {
throw Error('使用 .type 直接取值'); throw Error('使用 .type 直接取值');
if (ele.fnOptions) {
// 函数式组件
return ele.fnOptions;
}
let componentOptions = ele.componentOptions;
if (ele.$vnode) {
componentOptions = ele.$vnode.componentOptions;
}
return componentOptions ? componentOptions.Ctor.options || {} : {};
}; };
const findDOMNode = instance => { const findDOMNode = instance => {
let node = instance.$el || instance; let node = instance.$el || instance;
@ -148,7 +139,7 @@ const getOptionProps = instance => {
Object.keys(originProps).forEach(key => { Object.keys(originProps).forEach(key => {
props[camelize(key)] = originProps[key]; props[camelize(key)] = originProps[key];
}); });
const options = instance.type.props; const options = instance.type.props || {};
Object.keys(options).forEach(k => { Object.keys(options).forEach(k => {
const v = resolvePropValue(options, props, k, props[k]); const v = resolvePropValue(options, props, k, props[k]);
if (v !== undefined || k in props) { if (v !== undefined || k in props) {
@ -246,6 +237,7 @@ const getPropsData = ins => {
props[camelize(key)] = originProps[key]; props[camelize(key)] = originProps[key];
}); });
const options = isPlainObject(vnode.type) ? vnode.type.props : {}; const options = isPlainObject(vnode.type) ? vnode.type.props : {};
options &&
Object.keys(options).forEach(k => { Object.keys(options).forEach(k => {
const v = resolvePropValue(options, props, k, props[k]); const v = resolvePropValue(options, props, k, props[k]);
if (k in props) { if (k in props) {

View File

@ -302,7 +302,6 @@ const Cascader = {
}, },
generateFilteredOptions(prefixCls, renderEmpty) { generateFilteredOptions(prefixCls, renderEmpty) {
const h = this.$createElement;
const { showSearch, notFoundContent } = this; const { showSearch, notFoundContent } = this;
const names = getFilledFieldNames(this.$props); const names = getFilledFieldNames(this.$props);
const { const {
@ -356,7 +355,7 @@ const Cascader = {
} }
return [ return [
{ {
[names.label]: notFoundContent || renderEmpty(h, 'Cascader'), [names.label]: notFoundContent || renderEmpty('Cascader'),
[names.value]: 'ANT_CASCADER_NOT_FOUND', [names.value]: 'ANT_CASCADER_NOT_FOUND',
disabled: true, disabled: true,
}, },
@ -543,4 +542,8 @@ const Cascader = {
}, },
}; };
Cascader.install = function(app) {
app.component(Cascader.name, Cascader);
};
export default Cascader; export default Cascader;

View File

@ -96,7 +96,6 @@ export default {
return null; return null;
}, },
renderIndicator(h, prefixCls) { renderIndicator(h, prefixCls) {
// const h = this.$createElement
const dotClassName = `${prefixCls}-dot`; const dotClassName = `${prefixCls}-dot`;
let indicator = getComponent(this, 'indicator'); let indicator = getComponent(this, 'indicator');
// should not be render default indicator when indicator value is null // should not be render default indicator when indicator value is null

View File

@ -120,10 +120,9 @@ const Transfer = {
}, },
getLocale(transferLocale, renderEmpty) { getLocale(transferLocale, renderEmpty) {
const h = this.$createElement;
// Keep old locale props still working. // Keep old locale props still working.
const oldLocale = { const oldLocale = {
notFoundContent: renderEmpty(h, 'Transfer'), notFoundContent: renderEmpty('Transfer'),
}; };
const notFoundContent = getComponentFromProp(this, 'notFoundContent'); const notFoundContent = getComponentFromProp(this, 'notFoundContent');
if (notFoundContent) { if (notFoundContent) {

View File

@ -174,7 +174,7 @@ export default {
if (!listBody) { if (!listBody) {
let bodyNode; let bodyNode;
const { bodyContent, customize } = renderListNode(this.$createElement, renderList, { const { bodyContent, customize } = renderListNode(renderList, {
props: { ...this.$props, filteredItems, filteredRenderItems, selectedKeys: checkedKeys }, props: { ...this.$props, filteredItems, filteredRenderItems, selectedKeys: checkedKeys },
on: getListeners(this), on: getListeners(this),
}); });

View File

@ -1,16 +1,10 @@
import VcTreeSelect, { TreeNode, SHOW_ALL, SHOW_PARENT, SHOW_CHILD } from '../vc-tree-select'; import VcTreeSelect, { TreeNode, SHOW_ALL, SHOW_PARENT, SHOW_CHILD } from '../vc-tree-select';
import { inject } from 'vue';
import classNames from 'classnames'; import classNames from 'classnames';
import { TreeSelectProps } from './interface'; import { TreeSelectProps } from './interface';
import warning from '../_util/warning'; import warning from '../_util/warning';
import { import { initDefaultProps, getOptionProps, getComponent, getSlot } from '../_util/props-util';
initDefaultProps,
getOptionProps,
getComponentFromProp,
filterEmpty,
getListeners,
} from '../_util/props-util';
import { ConfigConsumerProps } from '../config-provider'; import { ConfigConsumerProps } from '../config-provider';
import Base from '../base';
export { TreeData, TreeSelectProps } from './interface'; export { TreeData, TreeSelectProps } from './interface';
import LoadingOutlined from '@ant-design/icons-vue/LoadingOutlined'; import LoadingOutlined from '@ant-design/icons-vue/LoadingOutlined';
@ -19,24 +13,26 @@ import DownOutlined from '@ant-design/icons-vue/DownOutlined';
import CloseOutlined from '@ant-design/icons-vue/CloseOutlined'; import CloseOutlined from '@ant-design/icons-vue/CloseOutlined';
import CloseCircleOutlined from '@ant-design/icons-vue/CloseCircleOutlined'; import CloseCircleOutlined from '@ant-design/icons-vue/CloseCircleOutlined';
import omit from 'omit.js'; import omit from 'omit.js';
const ATreeSelectNode = function ATreeSelectNode(props, ctx) {
return TreeNode(props, ctx);
};
Object.keys(TreeNode).forEach(key => (ATreeSelectNode[key] = TreeNode[key]));
const TreeSelect = { const TreeSelect = {
TreeNode: { ...TreeNode, name: 'ATreeSelectNode' }, TreeNode: ATreeSelectNode,
SHOW_ALL, SHOW_ALL,
SHOW_PARENT, SHOW_PARENT,
SHOW_CHILD, SHOW_CHILD,
inheritAttrs: false,
name: 'ATreeSelect', name: 'ATreeSelect',
props: initDefaultProps(TreeSelectProps(), { props: initDefaultProps(TreeSelectProps(), {
transitionName: 'slide-up', transitionName: 'slide-up',
choiceTransitionName: 'zoom', choiceTransitionName: 'zoom',
showSearch: false, showSearch: false,
}), }),
model: { setup() {
prop: 'value', return {
event: 'change', configProvider: inject('configProvider', ConfigConsumerProps),
}, };
inject: {
configProvider: { default: () => ConfigConsumerProps },
}, },
created() { created() {
warning( warning(
@ -46,12 +42,15 @@ const TreeSelect = {
); );
}, },
methods: { methods: {
saveTreeSelect(node) {
this.vcTreeSelect = node;
},
focus() { focus() {
this.$refs.vcTreeSelect.focus(); this.vcTreeSelect.focus();
}, },
blur() { blur() {
this.$refs.vcTreeSelect.blur(); this.vcTreeSelect.blur();
}, },
renderSwitcherIcon(prefixCls, { isLeaf, loading }) { renderSwitcherIcon(prefixCls, { isLeaf, loading }) {
if (loading) { if (loading) {
@ -62,11 +61,12 @@ const TreeSelect = {
} }
return <CaretDownOutlined class={`${prefixCls}-switcher-icon`} />; return <CaretDownOutlined class={`${prefixCls}-switcher-icon`} />;
}, },
onChange() { onChange(...args) {
this.$emit('change', ...arguments); this.$emit('update:value', args[0]);
this.$emit('change', ...args);
}, },
updateTreeData(treeData) { updateTreeData(treeData) {
const { $scopedSlots } = this; const { $slots } = this;
const defaultFields = { const defaultFields = {
children: 'children', children: 'children',
title: 'title', title: 'title',
@ -76,19 +76,19 @@ const TreeSelect = {
}; };
const replaceFields = { ...defaultFields, ...this.$props.replaceFields }; const replaceFields = { ...defaultFields, ...this.$props.replaceFields };
return treeData.map(item => { return treeData.map(item => {
const { scopedSlots = {} } = item; const { slots = {} } = item;
const label = item[replaceFields.label]; const label = item[replaceFields.label];
const title = item[replaceFields.title]; const title = item[replaceFields.title];
const value = item[replaceFields.value]; const value = item[replaceFields.value];
const key = item[replaceFields.key]; const key = item[replaceFields.key];
const children = item[replaceFields.children]; const children = item[replaceFields.children];
let newLabel = typeof label === 'function' ? label(this.$createElement) : label; let newLabel = typeof label === 'function' ? label() : label;
let newTitle = typeof title === 'function' ? title(this.$createElement) : title; let newTitle = typeof title === 'function' ? title() : title;
if (!newLabel && scopedSlots.label && $scopedSlots[scopedSlots.label]) { if (!newLabel && slots.label && $slots[slots.label]) {
newLabel = $scopedSlots.label(item); newLabel = $slots.label(item);
} }
if (!newTitle && scopedSlots.title && $scopedSlots[scopedSlots.title]) { if (!newTitle && slots.title && $slots[slots.title]) {
newTitle = $scopedSlots.title(item); newTitle = $slots.title(item);
} }
const treeNodeProps = { const treeNodeProps = {
...item, ...item,
@ -105,7 +105,7 @@ const TreeSelect = {
}, },
}, },
render(h) { render() {
const props = getOptionProps(this); const props = getOptionProps(this);
const { const {
prefixCls: customizePrefixCls, prefixCls: customizePrefixCls,
@ -115,13 +115,14 @@ const TreeSelect = {
getPopupContainer, getPopupContainer,
...restProps ...restProps
} = props; } = props;
const { class: className } = this.$attrs;
const getPrefixCls = this.configProvider.getPrefixCls; const getPrefixCls = this.configProvider.getPrefixCls;
const prefixCls = getPrefixCls('select', customizePrefixCls); const prefixCls = getPrefixCls('select', customizePrefixCls);
const renderEmpty = this.configProvider.renderEmpty; const renderEmpty = this.configProvider.renderEmpty;
const notFoundContent = getComponentFromProp(this, 'notFoundContent'); const notFoundContent = getComponent(this, 'notFoundContent');
const removeIcon = getComponentFromProp(this, 'removeIcon'); const removeIcon = getComponent(this, 'removeIcon');
const clearIcon = getComponentFromProp(this, 'clearIcon'); const clearIcon = getComponent(this, 'clearIcon');
const { getPopupContainer: getContextPopupContainer } = this.configProvider; const { getPopupContainer: getContextPopupContainer } = this.configProvider;
const rest = omit(restProps, [ const rest = omit(restProps, [
'inputIcon', 'inputIcon',
@ -130,7 +131,7 @@ const TreeSelect = {
'switcherIcon', 'switcherIcon',
'suffixIcon', 'suffixIcon',
]); ]);
let suffixIcon = getComponentFromProp(this, 'suffixIcon'); let suffixIcon = getComponent(this, 'suffixIcon');
suffixIcon = Array.isArray(suffixIcon) ? suffixIcon[0] : suffixIcon; suffixIcon = Array.isArray(suffixIcon) ? suffixIcon[0] : suffixIcon;
let treeData = props.treeData; let treeData = props.treeData;
if (treeData) { if (treeData) {
@ -139,6 +140,7 @@ const TreeSelect = {
const cls = { const cls = {
[`${prefixCls}-lg`]: size === 'large', [`${prefixCls}-lg`]: size === 'large',
[`${prefixCls}-sm`]: size === 'small', [`${prefixCls}-sm`]: size === 'small',
[className]: className,
}; };
// showSearch: single - false, multiple - true // showSearch: single - false, multiple - true
@ -147,7 +149,7 @@ const TreeSelect = {
showSearch = !!(restProps.multiple || restProps.treeCheckable); showSearch = !!(restProps.multiple || restProps.treeCheckable);
} }
let checkable = getComponentFromProp(this, 'treeCheckable'); let checkable = getComponent(this, 'treeCheckable');
if (checkable) { if (checkable) {
checkable = <span class={`${prefixCls}-tree-checkbox-inner`} />; checkable = <span class={`${prefixCls}-tree-checkbox-inner`} />;
} }
@ -160,7 +162,8 @@ const TreeSelect = {
<CloseCircleOutlined class={`${prefixCls}-clear-icon`} theme="filled" /> <CloseCircleOutlined class={`${prefixCls}-clear-icon`} theme="filled" />
); );
const VcTreeSelectProps = { const VcTreeSelectProps = {
props: Object.assign( ...this.$attrs,
...Object.assign(
{ {
switcherIcon: nodeProps => this.renderSwitcherIcon(prefixCls, nodeProps), switcherIcon: nodeProps => this.renderSwitcherIcon(prefixCls, nodeProps),
inputIcon, inputIcon,
@ -173,25 +176,24 @@ const TreeSelect = {
prefixCls, prefixCls,
dropdownStyle: { maxHeight: '100vh', overflow: 'auto', ...dropdownStyle }, dropdownStyle: { maxHeight: '100vh', overflow: 'auto', ...dropdownStyle },
treeCheckable: checkable, treeCheckable: checkable,
notFoundContent: notFoundContent || renderEmpty(h, 'Select'), notFoundContent: notFoundContent || renderEmpty('Select'),
__propsSymbol__: Symbol(), __propsSymbol__: Symbol(),
}, },
treeData ? { treeData } : {}, treeData ? { treeData } : {},
), ),
class: cls, class: cls,
on: { ...getListeners(this), change: this.onChange }, onChange: this.onChange,
ref: 'vcTreeSelect', ref: this.saveTreeSelect,
scopedSlots: this.$scopedSlots, children: getSlot(this),
}; };
return <VcTreeSelect {...VcTreeSelectProps}>{filterEmpty(this.$slots.default)}</VcTreeSelect>; return <VcTreeSelect {...VcTreeSelectProps} vSlots={omit(this.$slots, ['default'])} />;
}, },
}; };
/* istanbul ignore next */ /* istanbul ignore next */
TreeSelect.install = function(Vue) { TreeSelect.install = function(app) {
Vue.use(Base); app.component(TreeSelect.name, TreeSelect);
Vue.component(TreeSelect.name, TreeSelect); app.component(TreeSelect.TreeNode.name, TreeSelect.TreeNode);
Vue.component(TreeSelect.TreeNode.name, TreeSelect.TreeNode);
}; };
export default TreeSelect; export default TreeSelect;

View File

@ -54,4 +54,6 @@ export const TreeSelectProps = () => ({
treeNodeFilterProp: PropTypes.string, treeNodeFilterProp: PropTypes.string,
treeNodeLabelProp: PropTypes.string, treeNodeLabelProp: PropTypes.string,
replaceFields: PropTypes.object.def({}), replaceFields: PropTypes.object.def({}),
clearIcon: PropTypes.any,
removeIcon: PropTypes.any,
}); });

View File

@ -1,10 +1,6 @@
// export this package's api // export this package's api
// base 2.9.3 // base 2.9.3
import Vue from 'vue';
import TreeSelect from './src'; import TreeSelect from './src';
import ref from 'vue-ref';
Vue.use(ref, { name: 'ant-ref' });
export default TreeSelect; export default TreeSelect;
export { TreeNode, SHOW_ALL, SHOW_PARENT, SHOW_CHILD } from './src'; export { TreeNode, SHOW_ALL, SHOW_PARENT, SHOW_CHILD } from './src';

View File

@ -1,3 +1,4 @@
import { inject } from 'vue';
import warning from 'warning'; import warning from 'warning';
import PropTypes from '../../../_util/vue-types'; import PropTypes from '../../../_util/vue-types';
import { Tree } from '../../../vc-tree'; import { Tree } from '../../../vc-tree';
@ -69,6 +70,7 @@ function getDerivedState(nextProps, prevState) {
} }
const BasePopup = { const BasePopup = {
mixins: [BaseMixin], mixins: [BaseMixin],
inheritAttrs: false,
name: 'BasePopup', name: 'BasePopup',
props: { props: {
prefixCls: PropTypes.string, prefixCls: PropTypes.string,
@ -101,8 +103,10 @@ const BasePopup = {
__propsSymbol__: PropTypes.any, __propsSymbol__: PropTypes.any,
}, },
inject: { setup() {
vcTreeSelect: { default: () => ({}) }, return {
vcTreeSelect: inject('vcTreeSelect', {}),
};
}, },
watch: { watch: {
__propsSymbol__() { __propsSymbol__() {
@ -248,7 +252,6 @@ const BasePopup = {
$tree = $notFound; $tree = $notFound;
} else { } else {
const treeAllProps = { const treeAllProps = {
props: {
prefixCls: `${prefixCls}-tree`, prefixCls: `${prefixCls}-tree`,
showIcon: treeIcon, showIcon: treeIcon,
showLine: treeLine, showLine: treeLine,
@ -264,21 +267,12 @@ const BasePopup = {
...treeProps, ...treeProps,
__propsSymbol__: Symbol(), __propsSymbol__: Symbol(),
children: $treeNodes, children: $treeNodes,
}, onSelect: onTreeNodeSelect,
on: { onCheck: onTreeNodeCheck,
select: onTreeNodeSelect, onExpand: this.onTreeExpand,
check: onTreeNodeCheck, onLoad: this.onLoad,
expand: this.onTreeExpand,
load: this.onLoad,
},
directives: [
{
name: 'ant-ref',
value: this.treeRef,
},
],
}; };
$tree = <Tree {...treeAllProps} />; $tree = <Tree {...treeAllProps} ref={this.treeRef} />;
} }
return ( return (

View File

@ -5,14 +5,14 @@
* *
* So this file named as Selector to avoid confuse. * So this file named as Selector to avoid confuse.
*/ */
import { inject } from 'vue';
import { createRef } from '../util'; import { createRef } from '../util';
import PropTypes from '../../../_util/vue-types'; import PropTypes from '../../../_util/vue-types';
import classNames from 'classnames'; import classNames from 'classnames';
import { initDefaultProps, getComponentFromProp, getListeners } from '../../../_util/props-util'; import { initDefaultProps, getComponent } from '../../../_util/props-util';
import BaseMixin from '../../../_util/BaseMixin'; import BaseMixin from '../../../_util/BaseMixin';
export const selectorPropTypes = () => ({ export const selectorPropTypes = () => ({
prefixCls: PropTypes.string, prefixCls: PropTypes.string,
className: PropTypes.string,
open: PropTypes.bool, open: PropTypes.bool,
selectorValueList: PropTypes.array, selectorValueList: PropTypes.array,
allowClear: PropTypes.bool, allowClear: PropTypes.bool,
@ -36,6 +36,7 @@ function noop() {}
export default function(modeName) { export default function(modeName) {
const BaseSelector = { const BaseSelector = {
name: 'BaseSelector', name: 'BaseSelector',
inheritAttrs: false,
mixins: [BaseMixin], mixins: [BaseMixin],
props: initDefaultProps( props: initDefaultProps(
{ {
@ -50,8 +51,10 @@ export default function(modeName) {
tabindex: 0, tabindex: 0,
}, },
), ),
inject: { setup() {
vcTreeSelect: { default: () => ({}) }, return {
vcTreeSelect: inject('vcTreeSelect', {}),
};
}, },
created() { created() {
this.domRef = createRef(); this.domRef = createRef();
@ -96,7 +99,7 @@ export default function(modeName) {
if (!allowClear || !selectorValueList.length || !selectorValueList[0].value) { if (!allowClear || !selectorValueList.length || !selectorValueList[0].value) {
return null; return null;
} }
const clearIcon = getComponentFromProp(this, 'clearIcon'); const clearIcon = getComponent(this, 'clearIcon');
return ( return (
<span key="clear" class={`${prefixCls}-selection__clear`} onClick={onSelectorClear}> <span key="clear" class={`${prefixCls}-selection__clear`} onClick={onSelectorClear}>
{clearIcon} {clearIcon}
@ -109,7 +112,7 @@ export default function(modeName) {
if (!showArrow) { if (!showArrow) {
return null; return null;
} }
const inputIcon = getComponentFromProp(this, 'inputIcon'); const inputIcon = getComponent(this, 'inputIcon');
return ( return (
<span key="arrow" class={`${prefixCls}-arrow`} style={{ outline: 'none' }}> <span key="arrow" class={`${prefixCls}-arrow`} style={{ outline: 'none' }}>
{inputIcon} {inputIcon}
@ -121,8 +124,6 @@ export default function(modeName) {
render() { render() {
const { const {
prefixCls, prefixCls,
className,
style,
open, open,
focused, focused,
disabled, disabled,
@ -132,6 +133,7 @@ export default function(modeName) {
renderPlaceholder, renderPlaceholder,
tabindex, tabindex,
} = this.$props; } = this.$props;
const { class: className, style, onClick = noop } = this.$attrs;
const { const {
vcTreeSelect: { onSelectorKeyDown }, vcTreeSelect: { onSelectorKeyDown },
} = this; } = this;
@ -144,7 +146,7 @@ export default function(modeName) {
return ( return (
<span <span
style={style} style={style}
onClick={getListeners(this).click || noop} onClick={onClick}
class={classNames(className, prefixCls, { class={classNames(className, prefixCls, {
[`${prefixCls}-open`]: open, [`${prefixCls}-open`]: open,
[`${prefixCls}-focused`]: open || focused, [`${prefixCls}-focused`]: open || focused,
@ -152,14 +154,7 @@ export default function(modeName) {
[`${prefixCls}-enabled`]: !disabled, [`${prefixCls}-enabled`]: !disabled,
[`${prefixCls}-allow-clear`]: allowClear, [`${prefixCls}-allow-clear`]: allowClear,
})} })}
{...{ ref={this.domRef}
directives: [
{
name: 'ant-ref',
value: this.domRef,
},
],
}}
role="combobox" role="combobox"
aria-expanded={open} aria-expanded={open}
aria-owns={open ? ariaId : undefined} aria-owns={open ? ariaId : undefined}

View File

@ -2,10 +2,10 @@ import PropTypes from '../../../_util/vue-types';
import BasePopup from '../Base/BasePopup'; import BasePopup from '../Base/BasePopup';
import SearchInput from '../SearchInput'; import SearchInput from '../SearchInput';
import { createRef } from '../util'; import { createRef } from '../util';
import { getListeners } from '../../../_util/props-util';
const SinglePopup = { const SinglePopup = {
name: 'SinglePopup', name: 'SinglePopup',
inheritAttrs: false,
props: { props: {
...BasePopup.props, ...BasePopup.props,
...SearchInput.props, ...SearchInput.props,
@ -55,28 +55,10 @@ const SinglePopup = {
} }
return ( return (
<span <span class={`${dropdownPrefixCls}-search`} ref={this.searchRef}>
class={`${dropdownPrefixCls}-search`}
{...{
directives: [
{
name: 'ant-ref',
value: this.searchRef,
},
],
}}
>
<SearchInput <SearchInput
{...{ {...{ ...this.$props, ...this.$attrs, renderPlaceholder: this._renderPlaceholder }}
props: { ...this.$props, renderPlaceholder: this._renderPlaceholder }, ref={this.inputRef}
on: getListeners(this),
directives: [
{
name: 'ant-ref',
value: this.inputRef,
},
],
}}
/> />
</span> </span>
); );
@ -86,15 +68,12 @@ const SinglePopup = {
return ( return (
<BasePopup <BasePopup
{...{ {...{
props: { ...this.$props, renderSearch: this._renderSearch, __propsSymbol__: Symbol() }, ...this.$props,
on: getListeners(this), ...this.$attrs,
directives: [ renderSearch: this._renderSearch,
{ __propsSymbol__: Symbol(),
name: 'ant-ref',
value: this.popupRef,
},
],
}} }}
ref={this.popupRef}
/> />
); );
}, },

View File

@ -4,12 +4,13 @@
* - multiple: in the selector * - multiple: in the selector
* Move the code as a SearchInput for easy management. * Move the code as a SearchInput for easy management.
*/ */
import { inject } from 'vue';
import PropTypes from '../../_util/vue-types'; import PropTypes from '../../_util/vue-types';
import { createRef } from './util'; import { createRef } from './util';
const SearchInput = { const SearchInput = {
name: 'SearchInput', name: 'SearchInput',
inheritAttrs: false,
props: { props: {
open: PropTypes.bool, open: PropTypes.bool,
searchValue: PropTypes.string, searchValue: PropTypes.string,
@ -19,8 +20,10 @@ const SearchInput = {
needAlign: PropTypes.bool, needAlign: PropTypes.bool,
ariaId: PropTypes.string, ariaId: PropTypes.string,
}, },
inject: { setup() {
vcTreeSelect: { default: () => ({}) }, return {
vcTreeSelect: inject('vcTreeSelect', {}),
};
}, },
data() { data() {
return { return {
@ -117,17 +120,7 @@ const SearchInput = {
<span class={`${prefixCls}-search__field__wrap`}> <span class={`${prefixCls}-search__field__wrap`}>
<input <input
type="text" type="text"
{...{ ref={this.inputRef}
directives: [
{
name: 'ant-ref',
value: this.inputRef,
},
{
name: 'ant-input',
},
],
}}
onInput={handleInputChange} onInput={handleInputChange}
onKeydown={onSearchInputKeyDown} onKeydown={onSearchInputKeyDown}
value={searchValue} value={searchValue}
@ -138,17 +131,7 @@ const SearchInput = {
aria-controls={open ? ariaId : undefined} aria-controls={open ? ariaId : undefined}
aria-multiline="false" aria-multiline="false"
/> />
<span <span ref={this.mirrorInputRef} class={`${prefixCls}-search__field__mirror`}>
{...{
directives: [
{
name: 'ant-ref',
value: this.mirrorInputRef,
},
],
}}
class={`${prefixCls}-search__field__mirror`}
>
{mirrorSearchValue}&nbsp; {mirrorSearchValue}&nbsp;
</span> </span>
{renderPlaceholder && !mirrorSearchValue ? renderPlaceholder() : null} {renderPlaceholder && !mirrorSearchValue ? renderPlaceholder() : null}

View File

@ -18,7 +18,7 @@
* In single mode, we should focus on the `span` * In single mode, we should focus on the `span`
* In multiple mode, we should focus on the `input` * In multiple mode, we should focus on the `input`
*/ */
import { provide } from 'vue';
import shallowEqual from 'shallowequal'; import shallowEqual from 'shallowequal';
import raf from 'raf'; import raf from 'raf';
import scrollIntoView from 'dom-scroll-into-view'; import scrollIntoView from 'dom-scroll-into-view';
@ -55,10 +55,8 @@ import SelectNode from './SelectNode';
import { import {
initDefaultProps, initDefaultProps,
getOptionProps, getOptionProps,
mergeProps,
getPropsData, getPropsData,
filterEmpty, findDOMNode,
getListeners,
} from '../../_util/props-util'; } from '../../_util/props-util';
function getWatch(keys = []) { function getWatch(keys = []) {
const watch = {}; const watch = {};
@ -71,6 +69,7 @@ function getWatch(keys = []) {
} }
const Select = { const Select = {
name: 'Select', name: 'Select',
inheritAttrs: false,
mixins: [BaseMixin], mixins: [BaseMixin],
props: initDefaultProps( props: initDefaultProps(
{ {
@ -193,10 +192,8 @@ const Select = {
...newState, ...newState,
}; };
}, },
created() {
provide() { provide('vcTreeSelect', {
return {
vcTreeSelect: {
onSelectorFocus: this.onSelectorFocus, onSelectorFocus: this.onSelectorFocus,
onSelectorBlur: this.onSelectorBlur, onSelectorBlur: this.onSelectorBlur,
onSelectorKeyDown: this.onComponentKeyDown, onSelectorKeyDown: this.onComponentKeyDown,
@ -209,8 +206,7 @@ const Select = {
onSearchInputChange: this.onSearchInputChange, onSearchInputChange: this.onSearchInputChange,
onSearchInputKeyDown: this.onSearchInputKeyDown, onSearchInputKeyDown: this.onSearchInputKeyDown,
}, });
};
}, },
watch: { watch: {
...getWatch(['treeData', 'defaultValue', 'value']), ...getWatch(['treeData', 'defaultValue', 'value']),
@ -238,7 +234,7 @@ const Select = {
const treeNode = domTreeNodes[key]; const treeNode = domTreeNodes[key];
if (treeNode) { if (treeNode) {
const domNode = treeNode.$el; const domNode = findDOMNode(treeNode);
raf(() => { raf(() => {
const popupNode = this.popup.$el; const popupNode = this.popup.$el;
const triggerContainer = findPopupContainer(popupNode, `${prefixCls}-dropdown`); const triggerContainer = findPopupContainer(popupNode, `${prefixCls}-dropdown`);
@ -267,7 +263,6 @@ const Select = {
methods: { methods: {
getDerivedState(nextProps, prevState) { getDerivedState(nextProps, prevState) {
const h = this.$createElement;
const { _prevProps: prevProps = {} } = prevState; const { _prevProps: prevProps = {} } = prevState;
const { const {
treeCheckable, treeCheckable,
@ -302,7 +297,7 @@ const Select = {
let treeDataChanged = false; let treeDataChanged = false;
let treeDataModeChanged = false; let treeDataModeChanged = false;
processState('treeData', propValue => { processState('treeData', propValue => {
treeNodes = convertDataToTree(h, propValue); treeNodes = convertDataToTree(propValue);
treeDataChanged = true; treeDataChanged = true;
}); });
@ -325,7 +320,7 @@ const Select = {
rootPId: null, rootPId: null,
...(treeDataSimpleMode !== true ? treeDataSimpleMode : {}), ...(treeDataSimpleMode !== true ? treeDataSimpleMode : {}),
}; };
treeNodes = convertDataToTree(h, parseSimpleTreeData(nextProps.treeData, simpleMapper)); treeNodes = convertDataToTree(parseSimpleTreeData(nextProps.treeData, simpleMapper));
} }
// If `treeData` not provide, use children TreeNodes // If `treeData` not provide, use children TreeNodes
@ -333,7 +328,7 @@ const Select = {
// processState('children', (propValue) => { // processState('children', (propValue) => {
// treeNodes = Array.isArray(propValue) ? propValue : [propValue] // treeNodes = Array.isArray(propValue) ? propValue : [propValue]
// }) // })
treeNodes = filterEmpty(this.$slots.default); treeNodes = this.children || [];
} }
// Convert `treeData` to entities // Convert `treeData` to entities
@ -462,7 +457,6 @@ const Select = {
} }
newState._filteredTreeNodes = getFilterTree( newState._filteredTreeNodes = getFilterTree(
this.$createElement,
newState._treeNodes || prevState._treeNodes, newState._treeNodes || prevState._treeNodes,
searchValue, searchValue,
filterTreeNodeFn, filterTreeNodeFn,
@ -868,7 +862,6 @@ const Select = {
this.setState({ this.setState({
_filteredTreeNodes: getFilterTree( _filteredTreeNodes: getFilterTree(
this.$createElement,
treeNodes, treeNodes,
value, value,
filterTreeNodeFn, filterTreeNodeFn,
@ -1012,7 +1005,7 @@ const Select = {
} }
// Only do the logic when `onChange` function provided // Only do the logic when `onChange` function provided
if (getListeners(this).change) { if (this.$attrs.onChange) {
let connectValueList; let connectValueList;
// Get value by mode // Get value by mode
@ -1038,6 +1031,7 @@ const Select = {
if (!this.isMultiple()) { if (!this.isMultiple()) {
returnValue = returnValue[0]; returnValue = returnValue[0];
} }
// this.__emit('update:value', returnValue);
this.__emit('change', returnValue, labelList, extra); this.__emit('change', returnValue, labelList, extra);
} }
}, },
@ -1072,8 +1066,8 @@ const Select = {
const isMultiple = this.isMultiple(); const isMultiple = this.isMultiple();
const passProps = { const passProps = {
props: {
...props, ...props,
...this.$attrs,
isMultiple, isMultiple,
valueList, valueList,
searchHalfCheckedKeys, searchHalfCheckedKeys,
@ -1086,61 +1080,31 @@ const Select = {
focused, focused,
dropdownPrefixCls: `${prefixCls}-dropdown`, dropdownPrefixCls: `${prefixCls}-dropdown`,
ariaId: this.ariaId, ariaId: this.ariaId,
}, onChoiceAnimationLeave: this.onChoiceAnimationLeave,
on: { vSlots: this.$slots,
...getListeners(this),
choiceAnimationLeave: this.onChoiceAnimationLeave,
},
scopedSlots: this.$scopedSlots,
}; };
const popupProps = mergeProps(passProps, { const popupProps = {
props: { ...passProps,
treeNodes, treeNodes,
filteredTreeNodes, filteredTreeNodes,
// Tree expanded control // Tree expanded control
treeExpandedKeys, treeExpandedKeys,
__propsSymbol__: Symbol(), __propsSymbol__: Symbol(),
}, onTreeExpanded: this.delayForcePopupAlign,
on: { ref: this.setPopupRef,
treeExpanded: this.delayForcePopupAlign, };
},
directives: [
{
name: 'ant-ref',
value: this.setPopupRef,
},
],
});
const Popup = isMultiple ? MultiplePopup : SinglePopup; const Popup = isMultiple ? MultiplePopup : SinglePopup;
const $popup = <Popup {...popupProps} />; const $popup = <Popup {...popupProps} />;
const Selector = isMultiple ? MultipleSelector : SingleSelector; const Selector = isMultiple ? MultipleSelector : SingleSelector;
const $selector = ( const $selector = <Selector {...passProps} ref={this.selectorRef} />;
<Selector const selectTriggerProps = {
{...passProps} ...passProps,
{...{
directives: [
{
name: 'ant-ref',
value: this.selectorRef,
},
],
}}
/>
);
const selectTriggerProps = mergeProps(passProps, {
props: {
popupElement: $popup, popupElement: $popup,
dropdownVisibleChange: this.onDropdownVisibleChange, dropdownVisibleChange: this.onDropdownVisibleChange,
}, ref: this.selectTriggerRef,
directives: [ };
{
name: 'ant-ref',
value: this.selectTriggerRef,
},
],
});
return <SelectTrigger {...selectTriggerProps}>{$selector}</SelectTrigger>; return <SelectTrigger {...selectTriggerProps}>{$selector}</SelectTrigger>;
}, },
}; };

View File

@ -4,29 +4,10 @@ import { TreeNode } from '../../vc-tree';
* Let's use SelectNode instead of TreeNode * Let's use SelectNode instead of TreeNode
* since TreeNode is so confuse here. * since TreeNode is so confuse here.
*/ */
export default { function SelectNode(_, { attrs, slots }) {
name: 'SelectNode', return <TreeNode {...attrs} vSlots={slots} />;
functional: true, }
isTreeNode: true,
props: TreeNode.props, SelectNode.isTreeNode = true;
render(h, context) { SelectNode.inheritAttrs = false;
const { props, slots, listeners, data, scopedSlots } = context; export default SelectNode;
const $slots = slots() || {};
const children = $slots.default;
const slotsKey = Object.keys($slots);
const scopedSlotsTemp = {}; // for vue 2.5.x
slotsKey.forEach(name => {
scopedSlotsTemp[name] = () => $slots[name];
});
const treeNodeProps = {
...data,
on: { ...listeners, ...data.nativeOn },
props,
scopedSlots: {
...scopedSlotsTemp,
...scopedSlots,
},
};
return <TreeNode {...treeNodeProps}>{children}</TreeNode>;
},
};

View File

@ -1,8 +1,8 @@
import PropTypes from '../../_util/vue-types'; import PropTypes from '../../_util/vue-types';
import Trigger from '../../vc-trigger'; import Trigger from '../../vc-trigger';
import { createRef } from './util'; import { createRef } from './util';
import classNames from 'classnames'; import classNames from 'classnames';
import { getSlot } from '../../_util/props-util';
const BUILT_IN_PLACEMENTS = { const BUILT_IN_PLACEMENTS = {
bottomLeft: { bottomLeft: {
@ -27,6 +27,7 @@ const BUILT_IN_PLACEMENTS = {
const SelectTrigger = { const SelectTrigger = {
name: 'SelectTrigger', name: 'SelectTrigger',
inheritAttrs: false,
props: { props: {
// Pass by outside user props // Pass by outside user props
disabled: PropTypes.bool, disabled: PropTypes.bool,
@ -93,14 +94,7 @@ const SelectTrigger = {
} }
return ( return (
<Trigger <Trigger
{...{ ref={this.triggerRef}
directives: [
{
name: 'ant-ref',
value: this.triggerRef,
},
],
}}
action={disabled ? [] : ['click']} action={disabled ? [] : ['click']}
popupPlacement="bottomLeft" popupPlacement="bottomLeft"
builtinPlacements={BUILT_IN_PLACEMENTS} builtinPlacements={BUILT_IN_PLACEMENTS}
@ -118,7 +112,7 @@ const SelectTrigger = {
})} })}
popupStyle={dropdownStyle} popupStyle={dropdownStyle}
> >
{this.$slots.default} {getSlot(this)}
</Trigger> </Trigger>
); );
}, },

View File

@ -1,10 +1,12 @@
import classNames from 'classnames';
import PropTypes from '../../../../_util/vue-types'; import PropTypes from '../../../../_util/vue-types';
import { toTitle, UNSELECTABLE_ATTRIBUTE, UNSELECTABLE_STYLE } from '../../util'; import { toTitle, UNSELECTABLE_ATTRIBUTE, UNSELECTABLE_STYLE } from '../../util';
import { getComponentFromProp, getListeners } from '../../../../_util/props-util'; import { getComponent } from '../../../../_util/props-util';
import BaseMixin from '../../../../_util/BaseMixin'; import BaseMixin from '../../../../_util/BaseMixin';
const Selection = { const Selection = {
mixins: [BaseMixin], mixins: [BaseMixin],
inheritAttrs: false,
props: { props: {
prefixCls: PropTypes.string, prefixCls: PropTypes.string,
maxTagTextLength: PropTypes.number, maxTagTextLength: PropTypes.number,
@ -28,18 +30,18 @@ const Selection = {
if (maxTagTextLength && typeof content === 'string' && content.length > maxTagTextLength) { if (maxTagTextLength && typeof content === 'string' && content.length > maxTagTextLength) {
content = `${content.slice(0, maxTagTextLength)}...`; content = `${content.slice(0, maxTagTextLength)}...`;
} }
const { class: className, style, onRemove } = this.$attrs;
return ( return (
<li <li
style={UNSELECTABLE_STYLE} style={{ ...UNSELECTABLE_STYLE, ...style }}
{...{ attrs: UNSELECTABLE_ATTRIBUTE }} {...UNSELECTABLE_ATTRIBUTE}
role="menuitem" role="menuitem"
class={`${prefixCls}-selection__choice`} class={classNames(`${prefixCls}-selection__choice`, className)}
title={toTitle(label)} title={toTitle(label)}
> >
{getListeners(this).remove && ( {onRemove && (
<span class={`${prefixCls}-selection__choice__remove`} onClick={this.onRemove}> <span class={`${prefixCls}-selection__choice__remove`} onClick={this.onRemove}>
{getComponentFromProp(this, 'removeIcon')} {getComponent(this, 'removeIcon')}
</span> </span>
)} )}
<span class={`${prefixCls}-selection__choice__content`}>{content}</span> <span class={`${prefixCls}-selection__choice__content`}>{content}</span>

View File

@ -1,9 +1,10 @@
import { inject, TransitionGroup } from 'vue';
import PropTypes from '../../../../_util/vue-types'; import PropTypes from '../../../../_util/vue-types';
import { createRef } from '../../util'; import { createRef } from '../../util';
import generateSelector, { selectorPropTypes } from '../../Base/BaseSelector'; import generateSelector, { selectorPropTypes } from '../../Base/BaseSelector';
import SearchInput from '../../SearchInput'; import SearchInput from '../../SearchInput';
import Selection from './Selection'; import Selection from './Selection';
import { getComponentFromProp, getListeners } from '../../../../_util/props-util'; import { getComponent, getSlot } from '../../../../_util/props-util';
import getTransitionProps from '../../../../_util/getTransitionProps'; import getTransitionProps from '../../../../_util/getTransitionProps';
import BaseMixin from '../../../../_util/BaseMixin'; import BaseMixin from '../../../../_util/BaseMixin';
const TREE_SELECT_EMPTY_VALUE_KEY = 'RC_TREE_SELECT_EMPTY_VALUE_KEY'; const TREE_SELECT_EMPTY_VALUE_KEY = 'RC_TREE_SELECT_EMPTY_VALUE_KEY';
@ -15,7 +16,9 @@ const Selector = generateSelector('multiple');
// } // }
const MultipleSelector = { const MultipleSelector = {
name: 'MultipleSelector',
mixins: [BaseMixin], mixins: [BaseMixin],
inheritAttrs: false,
props: { props: {
...selectorPropTypes(), ...selectorPropTypes(),
...SearchInput.props, ...SearchInput.props,
@ -28,8 +31,10 @@ const MultipleSelector = {
// onChoiceAnimationLeave: PropTypes.func, // onChoiceAnimationLeave: PropTypes.func,
}, },
inject: { setup() {
vcTreeSelect: { default: () => ({}) }, return {
vcTreeSelect: inject('vcTreeSelect', {}),
};
}, },
created() { created() {
this.inputRef = createRef(); this.inputRef = createRef();
@ -85,11 +90,10 @@ const MultipleSelector = {
labelInValue, labelInValue,
maxTagCount, maxTagCount,
} = this.$props; } = this.$props;
const children = getSlot(this);
const { const {
vcTreeSelect: { onMultipleSelectorRemove }, vcTreeSelect: { onMultipleSelectorRemove },
$slots,
} = this; } = this;
const listeners = getListeners(this);
// Check if `maxTagCount` is set // Check if `maxTagCount` is set
let myValueList = selectorValueList; let myValueList = selectorValueList;
if (maxTagCount >= 0) { if (maxTagCount >= 0) {
@ -99,23 +103,21 @@ const MultipleSelector = {
const selectedValueNodes = myValueList.map(({ label, value }) => ( const selectedValueNodes = myValueList.map(({ label, value }) => (
<Selection <Selection
{...{ {...{
props: {
...this.$props, ...this.$props,
label, label,
value, value,
}, onRemove: onMultipleSelectorRemove,
on: { ...listeners, remove: onMultipleSelectorRemove },
}} }}
key={value || TREE_SELECT_EMPTY_VALUE_KEY} key={value || TREE_SELECT_EMPTY_VALUE_KEY}
> >
{$slots.default} {children}
</Selection> </Selection>
)); ));
// Rest node count // Rest node count
if (maxTagCount >= 0 && maxTagCount < selectorValueList.length) { if (maxTagCount >= 0 && maxTagCount < selectorValueList.length) {
let content = `+ ${selectorValueList.length - maxTagCount} ...`; let content = `+ ${selectorValueList.length - maxTagCount} ...`;
const maxTagPlaceholder = getComponentFromProp(this, 'maxTagPlaceholder', {}, false); const maxTagPlaceholder = getComponent(this, 'maxTagPlaceholder', {}, false);
if (typeof maxTagPlaceholder === 'string') { if (typeof maxTagPlaceholder === 'string') {
content = maxTagPlaceholder; content = maxTagPlaceholder;
} else if (typeof maxTagPlaceholder === 'function') { } else if (typeof maxTagPlaceholder === 'function') {
@ -128,16 +130,13 @@ const MultipleSelector = {
const restNodeSelect = ( const restNodeSelect = (
<Selection <Selection
{...{ {...{
props: {
...this.$props, ...this.$props,
label: content, label: content,
value: null, value: null,
},
on: listeners,
}} }}
key="rc-tree-select-internal-max-tag-counter" key="rc-tree-select-internal-max-tag-counter"
> >
{$slots.default} {children}
</Selection> </Selection>
); );
@ -148,20 +147,13 @@ const MultipleSelector = {
<li class={`${prefixCls}-search ${prefixCls}-search--inline`} key="__input"> <li class={`${prefixCls}-search ${prefixCls}-search--inline`} key="__input">
<SearchInput <SearchInput
{...{ {...{
props: {
...this.$props, ...this.$props,
...this.$attrs,
needAlign: true, needAlign: true,
},
on: listeners,
directives: [
{
name: 'ant-ref',
value: this.inputRef,
},
],
}} }}
ref={this.inputRef}
> >
{$slots.default} {children}
</SearchInput> </SearchInput>
</li>, </li>,
); );
@ -169,12 +161,12 @@ const MultipleSelector = {
if (choiceTransitionName) { if (choiceTransitionName) {
const transitionProps = getTransitionProps(choiceTransitionName, { const transitionProps = getTransitionProps(choiceTransitionName, {
tag: 'ul', tag: 'ul',
afterLeave: this.onChoiceAnimationLeave, onAfterLeave: this.onChoiceAnimationLeave,
}); });
return ( return (
<transition-group class={className} {...transitionProps}> <TransitionGroup class={className} {...transitionProps}>
{selectedValueNodes} {selectedValueNodes}
</transition-group> </TransitionGroup>
); );
} }
return ( return (
@ -186,22 +178,18 @@ const MultipleSelector = {
}, },
render() { render() {
const { $slots } = this;
const listeners = getListeners(this);
return ( return (
<Selector <Selector
{...{ {...{
props: {
...this.$props, ...this.$props,
...this.$attrs,
tabindex: -1, tabindex: -1,
showArrow: false, showArrow: false,
renderSelection: this.renderSelection, renderSelection: this.renderSelection,
renderPlaceholder: this._renderPlaceholder, renderPlaceholder: this._renderPlaceholder,
},
on: listeners,
}} }}
> >
{$slots.default} {getSlot(this)}
</Selector> </Selector>
); );
}, },

View File

@ -1,11 +1,12 @@
import generateSelector, { selectorPropTypes } from '../Base/BaseSelector'; import generateSelector, { selectorPropTypes } from '../Base/BaseSelector';
import { toTitle } from '../util'; import { toTitle } from '../util';
import { getOptionProps, getListeners } from '../../../_util/props-util'; import { getOptionProps } from '../../../_util/props-util';
import { createRef } from '../util'; import { createRef } from '../util';
const Selector = generateSelector('single'); const Selector = generateSelector('single');
const SingleSelector = { const SingleSelector = {
name: 'SingleSelector', name: 'SingleSelector',
inheritAttrs: false,
props: selectorPropTypes(), props: selectorPropTypes(),
created() { created() {
this.selectorRef = createRef(); this.selectorRef = createRef();
@ -43,17 +44,10 @@ const SingleSelector = {
render() { render() {
const props = { const props = {
props: {
...getOptionProps(this), ...getOptionProps(this),
...this.$attrs,
renderSelection: this.renderSelection, renderSelection: this.renderSelection,
}, ref: this.selectorRef,
on: getListeners(this),
directives: [
{
name: 'ant-ref',
value: this.selectorRef,
},
],
}; };
return <Selector {...props} />; return <Selector {...props} />;
}, },

View File

@ -1,5 +1,4 @@
import warning from 'warning'; import warning from 'warning';
import omit from 'omit.js';
import { import {
convertDataToTree as vcConvertDataToTree, convertDataToTree as vcConvertDataToTree,
convertTreeToEntities as vcConvertTreeToEntities, convertTreeToEntities as vcConvertTreeToEntities,
@ -7,7 +6,7 @@ import {
} from '../../vc-tree/src/util'; } from '../../vc-tree/src/util';
import { hasClass } from '../../vc-util/Dom/class'; import { hasClass } from '../../vc-util/Dom/class';
import { SHOW_CHILD, SHOW_PARENT } from './strategies'; import { SHOW_CHILD, SHOW_PARENT } from './strategies';
import { getSlots, getPropsData, isEmptyElement } from '../../_util/props-util'; import { getSlot, getPropsData, isEmptyElement } from '../../_util/props-util';
let warnDeprecatedLabel = false; let warnDeprecatedLabel = false;
@ -203,7 +202,7 @@ export function cleanEntity({ node, pos, children }) {
* we have to convert `treeNodes > data > treeNodes` to keep the key. * we have to convert `treeNodes > data > treeNodes` to keep the key.
* Such performance hungry! * Such performance hungry!
*/ */
export function getFilterTree(h, treeNodes, searchValue, filterFunc, valueEntities, Component) { export function getFilterTree(treeNodes, searchValue, filterFunc, valueEntities, Component) {
if (!searchValue) { if (!searchValue) {
return null; return null;
} }
@ -215,13 +214,13 @@ export function getFilterTree(h, treeNodes, searchValue, filterFunc, valueEntiti
if (filterFunc(searchValue, node)) { if (filterFunc(searchValue, node)) {
match = true; match = true;
} }
let children = getSlots(node).default; let children = getSlot(node);
children = ((typeof children === 'function' ? children() : children) || []) children = ((typeof children === 'function' ? children() : children) || [])
.map(mapFilteredNodeToData) .map(mapFilteredNodeToData)
.filter(n => n); .filter(n => n);
if (children.length || match) { if (children.length || match) {
return ( return (
<Component {...node.data} key={valueEntities[getPropsData(node).value].key}> <Component {...node.props} key={valueEntities[getPropsData(node).value].key}>
{children} {children}
</Component> </Component>
); );
@ -341,18 +340,8 @@ export function formatSelectorValue(valueList, props, valueEntities) {
* This will change the label to title value * This will change the label to title value
*/ */
function processProps(props) { function processProps(props) {
const { title, label, value, class: cls, style, on = {} } = props; const { title, label, key, value } = props;
let key = props.key; const cloneProps = { ...props };
if (!key && (key === undefined || key === null)) {
key = value;
}
const p = {
props: omit(props, ['on', 'key', 'class', 'className', 'style']),
on,
class: cls || props.className,
style,
key,
};
// Warning user not to use deprecated label prop. // Warning user not to use deprecated label prop.
if (label && !title) { if (label && !title) {
if (!warnDeprecatedLabel) { if (!warnDeprecatedLabel) {
@ -360,14 +349,18 @@ function processProps(props) {
warnDeprecatedLabel = true; warnDeprecatedLabel = true;
} }
p.props.title = label; cloneProps.title = label;
} }
return p; if (!key && (key === undefined || key === null)) {
cloneProps.key = value;
}
return cloneProps;
} }
export function convertDataToTree(h, treeData) { export function convertDataToTree(treeData) {
return vcConvertDataToTree(h, treeData, { processProps }); return vcConvertDataToTree(treeData, { processProps });
} }
/** /**

View File

@ -40,7 +40,7 @@ export function getPosition(level, index) {
} }
export function isTreeNode(node) { export function isTreeNode(node) {
return typeof node.type === 'object' && node.type.isTreeNode; return node.type && node.type.isTreeNode;
} }
export function getNodeChildren(children = []) { export function getNodeChildren(children = []) {

View File

@ -92,6 +92,7 @@ export default {
}; };
}); });
this._component = null; this._component = null;
this.focusTime = null;
return { return {
prevPopupVisible: popupVisible, prevPopupVisible: popupVisible,
sPopupVisible: popupVisible, sPopupVisible: popupVisible,

View File

@ -4,7 +4,7 @@
</div> </div>
</template> </template>
<script> <script>
import demo from '../antdv-demo/docs/tree/demo/directory'; import demo from '../antdv-demo/docs/tree-select/demo/treeData';
export default { export default {
components: { components: {

View File

@ -28,6 +28,7 @@ import {
Card, Card,
Avatar, Avatar,
Tree, Tree,
TreeSelect,
notification, notification,
message, message,
} from 'ant-design-vue'; } from 'ant-design-vue';
@ -45,11 +46,11 @@ const app = createApp(App);
app.config.globalProperties.$notification = notification; app.config.globalProperties.$notification = notification;
app.config.globalProperties.$message = message; app.config.globalProperties.$message = message;
app app
.component('demo-sort', { ...basic }) // .component('demo-sort', { ...basic })
.component('md', { ...basic }) // .component('md', { ...basic })
.component('api', { ...basic }) // .component('api', { ...basic })
.component('CN', { ...basic }) // .component('CN', { ...basic })
.component('US', { ...basic }) // .component('US', { ...basic })
.use(Pagination) .use(Pagination)
.use(Select) .use(Select)
.use(Spin) .use(Spin)
@ -76,4 +77,5 @@ app
.use(Avatar) .use(Avatar)
.use(Card) .use(Card)
.use(Tree) .use(Tree)
.use(TreeSelect)
.mount('#app'); .mount('#app');