feat: tree add blockNode selectable

pull/1845/head
tangjinzhou 2020-02-26 12:03:27 +08:00
parent a07810568a
commit 5cf57f4f28
14 changed files with 259 additions and 151 deletions

View File

@ -1,5 +1,5 @@
module.exports = {
dev: {
componentName: 'tree-select', // dev components
componentName: 'tree', // dev components
},
};

View File

@ -4,7 +4,12 @@ import PropTypes from '../_util/vue-types';
import warning from '../_util/warning';
import { conductExpandParent, convertTreeToEntities } from '../vc-tree/src/util';
import Tree, { TreeProps } from './Tree';
import { calcRangeKeys, getFullKeyList } from './util';
import {
calcRangeKeys,
getFullKeyList,
convertDirectoryKeysToNodes,
getFullKeyListByTreeData,
} from './util';
import Icon from '../icon';
import BaseMixin from '../_util/BaseMixin';
import {
@ -64,7 +69,11 @@ export default {
// Expanded keys
if (defaultExpandAll) {
state._expandedKeys = getFullKeyList(this.$slots.default);
if (props.treeData) {
state._expandedKeys = getFullKeyListByTreeData(props.treeData);
} else {
state._expandedKeys = getFullKeyList(this.$slots.default);
}
} else if (defaultExpandParent) {
state._expandedKeys = conductExpandParent(expandedKeys || defaultExpandedKeys, keyEntities);
} else {
@ -125,6 +134,13 @@ export default {
const { eventKey = '' } = node;
const newState = {};
// We need wrap this event since some value is not same
const newEvent = {
...event,
selected: true, // Directory selected always true
};
// Windows / Mac single pick
const ctrlPick = nativeEvent.ctrlKey || nativeEvent.metaKey;
const shiftPick = nativeEvent.shiftKey;
@ -136,6 +152,7 @@ export default {
newSelectedKeys = keys;
this.lastSelectedKey = eventKey;
this.cachedSelectedKeys = newSelectedKeys;
newEvent.selectedNodes = convertDirectoryKeysToNodes(children, newSelectedKeys);
} else if (multiple && shiftPick) {
// Shift click
newSelectedKeys = Array.from(
@ -144,16 +161,18 @@ export default {
...calcRangeKeys(children, expandedKeys, eventKey, this.lastSelectedKey),
]),
);
newEvent.selectedNodes = convertDirectoryKeysToNodes(children, newSelectedKeys);
} else {
// Single click
newSelectedKeys = [eventKey];
this.lastSelectedKey = eventKey;
this.cachedSelectedKeys = newSelectedKeys;
newEvent.selectedNodes = [event.node];
}
newState._selectedKeys = newSelectedKeys;
this.$emit('update:selectedKeys', newSelectedKeys);
this.$emit('select', newSelectedKeys, event);
this.$emit('select', newSelectedKeys, newEvent);
this.setUncontrolledState(newState);
},

View File

@ -93,6 +93,7 @@ function TreeProps() {
* 替换treeNode中 title,key,children字段为treeData中对应的字段
*/
replaceFields: PropTypes.object,
blockNode: PropTypes.bool,
};
}
@ -111,6 +112,7 @@ export default {
on: animation,
props: { appear: null },
},
blockNode: false,
}),
inject: {
configProvider: { default: () => ConfigConsumerProps },
@ -128,32 +130,27 @@ export default {
if (loading) {
return <Icon type="loading" class={`${prefixCls}-switcher-loading-icon`} />;
}
if (showLine) {
if (isLeaf) {
return <Icon type="file" class={`${prefixCls}-switcher-line-icon`} />;
}
return (
<Icon
type={expanded ? 'minus-square' : 'plus-square'}
class={`${prefixCls}-switcher-line-icon`}
theme="outlined"
/>
);
} else {
const switcherCls = `${prefixCls}-switcher-icon`;
if (isLeaf) {
return null;
} else if (switcherIcon) {
const switcherOriginCls = getClass(switcherIcon[0]);
return cloneElement(switcherIcon, {
class: {
[switcherCls]: true,
},
});
} else {
return <Icon type="caret-down" class={`${prefixCls}-switcher-icon`} theme="filled" />;
}
if (isLeaf) {
return showLine ? <Icon type="file" class={`${prefixCls}-switcher-line-icon`} /> : null;
}
const switcherCls = `${prefixCls}-switcher-icon`;
if (switcherIcon) {
return cloneElement(switcherIcon, {
class: {
[switcherCls]: true,
},
});
}
return showLine ? (
<Icon
type={expanded ? 'minus-square' : 'plus-square'}
class={`${prefixCls}-switcher-line-icon`}
theme="outlined"
/>
) : (
<Icon type="caret-down" class={switcherCls} theme="filled" />
);
},
updateTreeData(treeData) {
const { $slots, $scopedSlots } = this;
@ -166,12 +163,17 @@ export default {
const treeNodeProps = {
...restProps,
icon:
$slots[slots.icon] ||
($scopedSlots[scopedSlots.icon] && $scopedSlots[scopedSlots.icon](item)) ||
$slots[slots.icon] ||
restProps.icon,
switcherIcon:
($scopedSlots[scopedSlots.switcherIcon] &&
$scopedSlots[scopedSlots.switcherIcon](item)) ||
$slots[slots.switcherIcon] ||
restProps.switcherIcon,
title:
$slots[slots.title] ||
($scopedSlots[scopedSlots.title] && $scopedSlots[scopedSlots.title](item)) ||
$slots[slots.title] ||
restProps[replaceFields.title],
dataRef: item,
on,
@ -188,7 +190,8 @@ export default {
},
render() {
const props = getOptionProps(this);
const { prefixCls: customizePrefixCls, showIcon, treeNodes } = props;
const { $slots, $scopedSlots } = this;
const { prefixCls: customizePrefixCls, showIcon, treeNodes, blockNode } = props;
const getPrefixCls = this.configProvider.getPrefixCls;
const prefixCls = getPrefixCls('tree', customizePrefixCls);
const switcherIcon = getComponentFromProp(this, 'switcherIcon');
@ -202,13 +205,16 @@ export default {
...props,
prefixCls,
checkable: checkable ? <span class={`${prefixCls}-checkbox-inner`} /> : checkable,
children: filterEmpty(this.$slots.default || []),
children: filterEmpty($scopedSlots.default ? $scopedSlots.default() : $slots.default),
__propsSymbol__: Symbol(),
switcherIcon: nodeProps => this.renderSwitcherIcon(prefixCls, switcherIcon, nodeProps),
},
on: getListeners(this),
ref: 'tree',
class: !showIcon && `${prefixCls}-icon-hide`,
class: {
[`${prefixCls}-icon-hide`]: !showIcon,
[`${prefixCls}-block-node`]: blockNode,
},
};
if (treeData) {
vcTreeProps.props.treeData = treeData;

View File

@ -109,25 +109,35 @@ exports[`renders ./components/tree/demo/dynamic.md correctly 1`] = `
`;
exports[`renders ./components/tree/demo/line.md correctly 1`] = `
<ul role="tree" unselectable="on" class="ant-tree ant-tree-show-line ant-tree-icon-hide">
<li role="treeitem" class="ant-tree-treenode-switcher-open"><span class="ant-tree-switcher ant-tree-switcher_open"><i aria-label="icon: minus-square" class="ant-tree-switcher-line-icon anticon anticon-minus-square"><svg viewBox="64 64 896 896" data-icon="minus-square" width="1em" height="1em" fill="currentColor" aria-hidden="true" focusable="false" class=""><path d="M328 544h368c4.4 0 8-3.6 8-8v-48c0-4.4-3.6-8-8-8H328c-4.4 0-8 3.6-8 8v48c0 4.4 3.6 8 8 8z"></path><path d="M880 112H144c-17.7 0-32 14.3-32 32v736c0 17.7 14.3 32 32 32h736c17.7 0 32-14.3 32-32V144c0-17.7-14.3-32-32-32zm-40 728H184V184h656v656z"></path></svg></i></span><span title="" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-open"><span class="ant-tree-title"><span style="color: rgb(24, 144, 255);">parent 1</span></span></span>
<ul data-expanded="true" role="group" class="ant-tree-child-tree ant-tree-child-tree-open">
<li role="treeitem" class="ant-tree-treenode-switcher-open"><span class="ant-tree-switcher ant-tree-switcher_open"><i aria-label="icon: minus-square" class="ant-tree-switcher-line-icon anticon anticon-minus-square"><svg viewBox="64 64 896 896" data-icon="minus-square" width="1em" height="1em" fill="currentColor" aria-hidden="true" focusable="false" class=""><path d="M328 544h368c4.4 0 8-3.6 8-8v-48c0-4.4-3.6-8-8-8H328c-4.4 0-8 3.6-8 8v48c0 4.4 3.6 8 8 8z"></path><path d="M880 112H144c-17.7 0-32 14.3-32 32v736c0 17.7 14.3 32 32 32h736c17.7 0 32-14.3 32-32V144c0-17.7-14.3-32-32-32zm-40 728H184V184h656v656z"></path></svg></i></span><span title="parent 1-0" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-open"><span class="ant-tree-title">parent 1-0</span></span>
<ul data-expanded="true" role="group" class="ant-tree-child-tree ant-tree-child-tree-open">
<li role="treeitem" class="ant-tree-treenode-switcher-close"><span class="ant-tree-switcher ant-tree-switcher-noop"><i aria-label="icon: file" class="ant-tree-switcher-line-icon anticon anticon-file"><svg viewBox="64 64 896 896" data-icon="file" width="1em" height="1em" fill="currentColor" aria-hidden="true" focusable="false" class=""><path d="M854.6 288.6L639.4 73.4c-6-6-14.1-9.4-22.6-9.4H192c-17.7 0-32 14.3-32 32v832c0 17.7 14.3 32 32 32h640c17.7 0 32-14.3 32-32V311.3c0-8.5-3.4-16.7-9.4-22.7zM790.2 326H602V137.8L790.2 326zm1.8 562H232V136h302v216a42 42 0 0 0 42 42h216v494z"></path></svg></i></span><span title="leaf" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-normal"><span class="ant-tree-title">leaf</span></span></li>
<li role="treeitem" class="ant-tree-treenode-switcher-close"><span class="ant-tree-switcher ant-tree-switcher-noop"><i aria-label="icon: file" class="ant-tree-switcher-line-icon anticon anticon-file"><svg viewBox="64 64 896 896" data-icon="file" width="1em" height="1em" fill="currentColor" aria-hidden="true" focusable="false" class=""><path d="M854.6 288.6L639.4 73.4c-6-6-14.1-9.4-22.6-9.4H192c-17.7 0-32 14.3-32 32v832c0 17.7 14.3 32 32 32h640c17.7 0 32-14.3 32-32V311.3c0-8.5-3.4-16.7-9.4-22.7zM790.2 326H602V137.8L790.2 326zm1.8 562H232V136h302v216a42 42 0 0 0 42 42h216v494z"></path></svg></i></span><span title="leaf" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-normal"><span class="ant-tree-title">leaf</span></span></li>
<li role="treeitem" class="ant-tree-treenode-switcher-close"><span class="ant-tree-switcher ant-tree-switcher-noop"><i aria-label="icon: file" class="ant-tree-switcher-line-icon anticon anticon-file"><svg viewBox="64 64 896 896" data-icon="file" width="1em" height="1em" fill="currentColor" aria-hidden="true" focusable="false" class=""><path d="M854.6 288.6L639.4 73.4c-6-6-14.1-9.4-22.6-9.4H192c-17.7 0-32 14.3-32 32v832c0 17.7 14.3 32 32 32h640c17.7 0 32-14.3 32-32V311.3c0-8.5-3.4-16.7-9.4-22.7zM790.2 326H602V137.8L790.2 326zm1.8 562H232V136h302v216a42 42 0 0 0 42 42h216v494z"></path></svg></i></span><span title="leaf" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-normal"><span class="ant-tree-title">leaf</span></span></li>
</ul>
</li>
<li role="treeitem" class="ant-tree-treenode-switcher-close"><span class="ant-tree-switcher ant-tree-switcher_close"><i aria-label="icon: plus-square" class="ant-tree-switcher-line-icon anticon anticon-plus-square"><svg viewBox="64 64 896 896" data-icon="plus-square" width="1em" height="1em" fill="currentColor" aria-hidden="true" focusable="false" class=""><path d="M328 544h152v152c0 4.4 3.6 8 8 8h48c4.4 0 8-3.6 8-8V544h152c4.4 0 8-3.6 8-8v-48c0-4.4-3.6-8-8-8H544V328c0-4.4-3.6-8-8-8h-48c-4.4 0-8 3.6-8 8v152H328c-4.4 0-8 3.6-8 8v48c0 4.4 3.6 8 8 8z"></path><path d="M880 112H144c-17.7 0-32 14.3-32 32v736c0 17.7 14.3 32 32 32h736c17.7 0 32-14.3 32-32V144c0-17.7-14.3-32-32-32zm-40 728H184V184h656v656z"></path></svg></i></span><span title="parent 1-1" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-close"><span class="ant-tree-title">parent 1-1</span></span>
<!---->
</li>
<li role="treeitem" class="ant-tree-treenode-switcher-close"><span class="ant-tree-switcher ant-tree-switcher_close"><i aria-label="icon: plus-square" class="ant-tree-switcher-line-icon anticon anticon-plus-square"><svg viewBox="64 64 896 896" data-icon="plus-square" width="1em" height="1em" fill="currentColor" aria-hidden="true" focusable="false" class=""><path d="M328 544h152v152c0 4.4 3.6 8 8 8h48c4.4 0 8-3.6 8-8V544h152c4.4 0 8-3.6 8-8v-48c0-4.4-3.6-8-8-8H544V328c0-4.4-3.6-8-8-8h-48c-4.4 0-8 3.6-8 8v152H328c-4.4 0-8 3.6-8 8v48c0 4.4 3.6 8 8 8z"></path><path d="M880 112H144c-17.7 0-32 14.3-32 32v736c0 17.7 14.3 32 32 32h736c17.7 0 32-14.3 32-32V144c0-17.7-14.3-32-32-32zm-40 728H184V184h656v656z"></path></svg></i></span><span title="parent 1-2" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-close"><span class="ant-tree-title">parent 1-2</span></span>
<!---->
</li>
</ul>
</li>
</ul>
<div>
<div style="margin-bottom: 16px;">
showLine: <button type="button" role="switch" aria-checked="true" class="ant-switch ant-switch-checked"><span class="ant-switch-inner"></span></button> <br> <br>
showIcon: <button type="button" role="switch" class="ant-switch"><span class="ant-switch-inner"></span></button></div>
<ul role="tree" unselectable="on" class="ant-tree ant-tree-show-line ant-tree-icon-hide">
<li role="treeitem" class="ant-tree-treenode-switcher-open"><span class="ant-tree-switcher ant-tree-switcher_open"><i aria-label="icon: minus-square" class="ant-tree-switcher-line-icon anticon anticon-minus-square"><svg viewBox="64 64 896 896" data-icon="minus-square" width="1em" height="1em" fill="currentColor" aria-hidden="true" focusable="false" class=""><path d="M328 544h368c4.4 0 8-3.6 8-8v-48c0-4.4-3.6-8-8-8H328c-4.4 0-8 3.6-8 8v48c0 4.4 3.6 8 8 8z"></path><path d="M880 112H144c-17.7 0-32 14.3-32 32v736c0 17.7 14.3 32 32 32h736c17.7 0 32-14.3 32-32V144c0-17.7-14.3-32-32-32zm-40 728H184V184h656v656z"></path></svg></i></span><span title="" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-open"><span class="ant-tree-title"><span style="color: rgb(24, 144, 255);">parent 1</span></span></span>
<ul data-expanded="true" role="group" class="ant-tree-child-tree ant-tree-child-tree-open">
<li role="treeitem" class="ant-tree-treenode-switcher-open"><span class="ant-tree-switcher ant-tree-switcher_open"><i aria-label="icon: minus-square" class="ant-tree-switcher-line-icon anticon anticon-minus-square"><svg viewBox="64 64 896 896" data-icon="minus-square" width="1em" height="1em" fill="currentColor" aria-hidden="true" focusable="false" class=""><path d="M328 544h368c4.4 0 8-3.6 8-8v-48c0-4.4-3.6-8-8-8H328c-4.4 0-8 3.6-8 8v48c0 4.4 3.6 8 8 8z"></path><path d="M880 112H144c-17.7 0-32 14.3-32 32v736c0 17.7 14.3 32 32 32h736c17.7 0 32-14.3 32-32V144c0-17.7-14.3-32-32-32zm-40 728H184V184h656v656z"></path></svg></i></span><span title="parent 1-0" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-open"><span class="ant-tree-title">parent 1-0</span></span>
<ul data-expanded="true" role="group" class="ant-tree-child-tree ant-tree-child-tree-open">
<li role="treeitem" class="ant-tree-treenode-switcher-close"><span class="ant-tree-switcher ant-tree-switcher-noop"><i aria-label="icon: file" class="ant-tree-switcher-line-icon anticon anticon-file"><svg viewBox="64 64 896 896" data-icon="file" width="1em" height="1em" fill="currentColor" aria-hidden="true" focusable="false" class=""><path d="M854.6 288.6L639.4 73.4c-6-6-14.1-9.4-22.6-9.4H192c-17.7 0-32 14.3-32 32v832c0 17.7 14.3 32 32 32h640c17.7 0 32-14.3 32-32V311.3c0-8.5-3.4-16.7-9.4-22.7zM790.2 326H602V137.8L790.2 326zm1.8 562H232V136h302v216a42 42 0 0 0 42 42h216v494z"></path></svg></i></span><span title="leaf" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-normal"><span class="ant-tree-title">leaf</span></span></li>
<li role="treeitem" class="ant-tree-treenode-switcher-close"><span class="ant-tree-switcher ant-tree-switcher-noop"><i aria-label="icon: file" class="ant-tree-switcher-line-icon anticon anticon-file"><svg viewBox="64 64 896 896" data-icon="file" width="1em" height="1em" fill="currentColor" aria-hidden="true" focusable="false" class=""><path d="M854.6 288.6L639.4 73.4c-6-6-14.1-9.4-22.6-9.4H192c-17.7 0-32 14.3-32 32v832c0 17.7 14.3 32 32 32h640c17.7 0 32-14.3 32-32V311.3c0-8.5-3.4-16.7-9.4-22.7zM790.2 326H602V137.8L790.2 326zm1.8 562H232V136h302v216a42 42 0 0 0 42 42h216v494z"></path></svg></i></span><span title="leaf" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-normal"><span class="ant-tree-title">leaf</span></span></li>
<li role="treeitem" class="ant-tree-treenode-switcher-close"><span class="ant-tree-switcher ant-tree-switcher-noop"><i aria-label="icon: file" class="ant-tree-switcher-line-icon anticon anticon-file"><svg viewBox="64 64 896 896" data-icon="file" width="1em" height="1em" fill="currentColor" aria-hidden="true" focusable="false" class=""><path d="M854.6 288.6L639.4 73.4c-6-6-14.1-9.4-22.6-9.4H192c-17.7 0-32 14.3-32 32v832c0 17.7 14.3 32 32 32h640c17.7 0 32-14.3 32-32V311.3c0-8.5-3.4-16.7-9.4-22.7zM790.2 326H602V137.8L790.2 326zm1.8 562H232V136h302v216a42 42 0 0 0 42 42h216v494z"></path></svg></i></span><span title="leaf" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-normal"><span class="ant-tree-title">leaf</span></span></li>
</ul>
</li>
<li role="treeitem" class="ant-tree-treenode-switcher-open"><span class="ant-tree-switcher ant-tree-switcher_open"><i aria-label="icon: minus-square" class="ant-tree-switcher-line-icon anticon anticon-minus-square"><svg viewBox="64 64 896 896" data-icon="minus-square" width="1em" height="1em" fill="currentColor" aria-hidden="true" focusable="false" class=""><path d="M328 544h368c4.4 0 8-3.6 8-8v-48c0-4.4-3.6-8-8-8H328c-4.4 0-8 3.6-8 8v48c0 4.4 3.6 8 8 8z"></path><path d="M880 112H144c-17.7 0-32 14.3-32 32v736c0 17.7 14.3 32 32 32h736c17.7 0 32-14.3 32-32V144c0-17.7-14.3-32-32-32zm-40 728H184V184h656v656z"></path></svg></i></span><span title="parent 1-1" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-open"><span class="ant-tree-title">parent 1-1</span></span>
<ul data-expanded="true" role="group" class="ant-tree-child-tree ant-tree-child-tree-open">
<li role="treeitem" class="ant-tree-treenode-switcher-close"><span class="ant-tree-switcher ant-tree-switcher-noop"><i aria-label="icon: file" class="ant-tree-switcher-line-icon anticon anticon-file"><svg viewBox="64 64 896 896" data-icon="file" width="1em" height="1em" fill="currentColor" aria-hidden="true" focusable="false" class=""><path d="M854.6 288.6L639.4 73.4c-6-6-14.1-9.4-22.6-9.4H192c-17.7 0-32 14.3-32 32v832c0 17.7 14.3 32 32 32h640c17.7 0 32-14.3 32-32V311.3c0-8.5-3.4-16.7-9.4-22.7zM790.2 326H602V137.8L790.2 326zm1.8 562H232V136h302v216a42 42 0 0 0 42 42h216v494z"></path></svg></i></span><span title="leaf" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-normal"><span class="ant-tree-title">leaf</span></span></li>
</ul>
</li>
<li role="treeitem" class="ant-tree-treenode-switcher-open"><span class="ant-tree-switcher ant-tree-switcher_open"><i aria-label="icon: minus-square" class="ant-tree-switcher-line-icon anticon anticon-minus-square"><svg viewBox="64 64 896 896" data-icon="minus-square" width="1em" height="1em" fill="currentColor" aria-hidden="true" focusable="false" class=""><path d="M328 544h368c4.4 0 8-3.6 8-8v-48c0-4.4-3.6-8-8-8H328c-4.4 0-8 3.6-8 8v48c0 4.4 3.6 8 8 8z"></path><path d="M880 112H144c-17.7 0-32 14.3-32 32v736c0 17.7 14.3 32 32 32h736c17.7 0 32-14.3 32-32V144c0-17.7-14.3-32-32-32zm-40 728H184V184h656v656z"></path></svg></i></span><span title="parent 1-2" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-open"><span class="ant-tree-title">parent 1-2</span></span>
<ul data-expanded="true" role="group" class="ant-tree-child-tree ant-tree-child-tree-open">
<li role="treeitem" class="ant-tree-treenode-switcher-close"><span class="ant-tree-switcher ant-tree-switcher-noop"><i aria-label="icon: file" class="ant-tree-switcher-line-icon anticon anticon-file"><svg viewBox="64 64 896 896" data-icon="file" width="1em" height="1em" fill="currentColor" aria-hidden="true" focusable="false" class=""><path d="M854.6 288.6L639.4 73.4c-6-6-14.1-9.4-22.6-9.4H192c-17.7 0-32 14.3-32 32v832c0 17.7 14.3 32 32 32h640c17.7 0 32-14.3 32-32V311.3c0-8.5-3.4-16.7-9.4-22.7zM790.2 326H602V137.8L790.2 326zm1.8 562H232V136h302v216a42 42 0 0 0 42 42h216v494z"></path></svg></i></span><span title="leaf" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-normal"><span class="ant-tree-title">leaf</span></span></li>
<li role="treeitem" class="ant-tree-treenode-switcher-close"><span class="ant-tree-switcher ant-tree-switcher-noop"><i slot="switcherIcon" aria-label="icon: form" class="anticon anticon-form"><svg viewBox="64 64 896 896" data-icon="form" width="1em" height="1em" fill="currentColor" aria-hidden="true" focusable="false" class=""><path d="M904 512h-56c-4.4 0-8 3.6-8 8v320H184V184h320c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H144c-17.7 0-32 14.3-32 32v736c0 17.7 14.3 32 32 32h736c17.7 0 32-14.3 32-32V520c0-4.4-3.6-8-8-8z"></path><path d="M355.9 534.9L354 653.8c-.1 8.9 7.1 16.2 16 16.2h.4l118-2.9c2-.1 4-.9 5.4-2.3l415.9-415c3.1-3.1 3.1-8.2 0-11.3L785.4 114.3c-1.6-1.6-3.6-2.3-5.7-2.3s-4.1.8-5.7 2.3l-415.8 415a8.3 8.3 0 0 0-2.3 5.6zm63.5 23.6L779.7 199l45.2 45.1-360.5 359.7-45.7 1.1.7-46.4z"></path></svg></i></span><span title="leaf" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-normal"><span class="ant-tree-title">leaf</span></span></li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
`;
exports[`renders ./components/tree/demo/replaceFields.md correctly 1`] = `

View File

@ -4,8 +4,8 @@
</cn>
<us>
#### basic controlled example
basic controlled example
#### Controlled Tree
Controlled mode lets parent nodes reflect the status of child nodes more intelligently.
</us>
```tpl

View File

@ -24,8 +24,8 @@ Built-in directory tree. `multiple` support `ctrl(Windows)` / `command(Mac)` sel
<script>
export default {
methods: {
onSelect(keys) {
console.log('Trigger Select', keys);
onSelect(keys, event) {
console.log('Trigger Select', keys, event);
},
onExpand() {
console.log('Trigger Expand');

View File

@ -10,27 +10,59 @@ Tree With Line
```tpl
<template>
<a-tree showLine :defaultExpandedKeys="['0-0-0']" @select="onSelect">
<div>
<div style="margin-bottom: 16px">
showLine: <a-switch v-model="showLine" />
<br />
<br />
showIcon: <a-switch v-model="showIcon" />
</div>
<a-tree :showLine="showLine" :showIcon="showIcon" :defaultExpandedKeys="['0-0-0', '0-0-1', '0-0-2']" @select="onSelect">
<a-icon slot="icon" type="carry-out" />
<a-tree-node key="0-0">
<a-icon slot="icon" type="carry-out" />
<span slot="title" style="color: #1890ff">parent 1</span>
<a-tree-node title="parent 1-0" key="0-0-0">
<a-tree-node title="leaf" key="0-0-0-0" />
<a-tree-node title="leaf" key="0-0-0-1" />
<a-tree-node title="leaf" key="0-0-0-2" />
<a-icon slot="icon" type="carry-out" />
<a-tree-node title="leaf" key="0-0-0-0">
<a-icon slot="icon" type="carry-out" />
</a-tree-node>
<a-tree-node title="leaf" key="0-0-0-1">
<a-icon slot="icon" type="carry-out" />
</a-tree-node>
<a-tree-node title="leaf" key="0-0-0-2">
<a-icon slot="icon" type="carry-out" />
</a-tree-node>
</a-tree-node>
<a-tree-node title="parent 1-1" key="0-0-1">
<a-tree-node title="leaf" key="0-0-1-0" />
<a-icon slot="icon" type="carry-out" />
<a-tree-node title="leaf" key="0-0-1-0">
<a-icon slot="icon" type="carry-out" />
</a-tree-node>
</a-tree-node>
<a-tree-node title="parent 1-2" key="0-0-2">
<a-tree-node title="leaf" key="0-0-2-0" />
<a-tree-node title="leaf" key="0-0-2-1" />
<a-icon slot="icon" type="carry-out" />
<a-tree-node title="leaf" key="0-0-2-0">
<a-icon slot="icon" type="carry-out" />
</a-tree-node>
<a-tree-node title="leaf" key="0-0-2-1">
<a-icon slot="icon" type="carry-out" />
<a-icon slot="switcherIcon" type="form" />
</a-tree-node>
</a-tree-node>
</a-tree-node>
</a-tree>
</div>
</template>
<script>
export default {
data() {
return {
showLine: true,
showIcon: false,
}
},
methods: {
onSelect(selectedKeys, info) {
console.log('selected', selectedKeys, info);

View File

@ -66,7 +66,7 @@ Searchable Tree.
const key = node.key;
dataList.push({ key, title: key });
if (node.children) {
generateList(node.children, node.key);
generateList(node.children);
}
}
};

View File

@ -2,30 +2,32 @@
### Tree props
| Property | Description | Type | Default |
| --- | --- | --- | --- |
| treeData | treeNode of tree, please use `treeNodes` before v1.1.4 | array | - |
| replaceFields | Replace the title,key and children fields in treeNode with the corresponding fields in treeData | object | { children:'children', title:'title', key:'key' } |
| autoExpandParent | Whether to automatically expand a parent treeNode | boolean | true |
| checkable | Adds a `Checkbox` before the treeNodes | boolean | false |
| checkedKeys(v-model) | (Controlled) Specifies the keys of the checked treeNodes (PS: When this specifies the key of a treeNode which is also a parent treeNode, all the children treeNodes of will be checked; and vice versa, when it specifies the key of a treeNode which is a child treeNode, its parent treeNode will also be checked. When `checkable` and `checkStrictly` is true, its object has `checked` and `halfChecked` property. Regardless of whether the child or parent treeNode is checked, they won't impact each other. | string\[] \| number\[] \| {checked: string\[] \| number\[], halfChecked: string\[] \| number\[]} | \[] |
| checkStrictly | Check treeNode precisely; parent treeNode and children treeNodes are not associated | boolean | false |
| defaultCheckedKeys | Specifies the keys of the default checked treeNodes | string\[] \| number\[] | \[] |
| defaultExpandAll | Whether to expand all treeNodes by default | boolean | false |
| defaultExpandedKeys | Specify the keys of the default expanded treeNodes | string\[] \| number\[] | \[] |
| defaultExpandParent | auto expand parent treeNodes when init | bool | true |
| defaultSelectedKeys | Specifies the keys of the default selected treeNodes | string\[] \| number\[] | \[] |
| disabled | whether disabled the tree | bool | false |
| draggable | Specifies whether this Tree is draggable (IE > 8) | boolean | false |
| expandedKeys(.sync) | (Controlled) Specifies the keys of the expanded treeNodes | string\[] \| number\[] | \[] |
| filterTreeNode | Defines a function to filter (highlight) treeNodes. When the function returns `true`, the corresponding treeNode will be highlighted | function(node) | - |
| loadData | Load data asynchronously | function(node) | - |
| loadedKeys | (Controlled) Set loaded tree nodes. Need work with `loadData` | string\[] \| number\[] | \[] |
| multiple | Allows selecting multiple treeNodes | boolean | false |
| selectedKeys(.sync) | (Controlled) Specifies the keys of the selected treeNodes | string\[] \| number\[] | - |
| showIcon | Shows the icon before a TreeNode's title. There is no default style; you must set a custom style for it if set to `true` | boolean | false |
| switcherIcon | customize collapse/expand icon of tree node | slot | - |
| showLine | Shows a connecting line | boolean | false |
| Property | Description | Type | Default | Version |
| --- | --- | --- | --- | --- |
| treeData | treeNode of tree, please use `treeNodes` before v1.1.4 | array | - | |
| replaceFields | Replace the title,key and children fields in treeNode with the corresponding fields in treeData | object | { children:'children', title:'title', key:'key' } | |
| autoExpandParent | Whether to automatically expand a parent treeNode | boolean | true | |
| blockNode | Whether treeNode fill remaining horizontal space | boolean | false | 1.5.0 |
| checkable | Adds a `Checkbox` before the treeNodes | boolean | false | |
| checkedKeys(v-model) | (Controlled) Specifies the keys of the checked treeNodes (PS: When this specifies the key of a treeNode which is also a parent treeNode, all the children treeNodes of will be checked; and vice versa, when it specifies the key of a treeNode which is a child treeNode, its parent treeNode will also be checked. When `checkable` and `checkStrictly` is true, its object has `checked` and `halfChecked` property. Regardless of whether the child or parent treeNode is checked, they won't impact each other. | string\[] \| number\[] \| {checked: string\[] \| number\[], halfChecked: string\[] \| number\[]} | \[] | |
| checkStrictly | Check treeNode precisely; parent treeNode and children treeNodes are not associated | boolean | false | |
| defaultCheckedKeys | Specifies the keys of the default checked treeNodes | string\[] \| number\[] | \[] | |
| defaultExpandAll | Whether to expand all treeNodes by default | boolean | false | |
| defaultExpandedKeys | Specify the keys of the default expanded treeNodes | string\[] \| number\[] | \[] | |
| defaultExpandParent | auto expand parent treeNodes when init | bool | true | |
| defaultSelectedKeys | Specifies the keys of the default selected treeNodes | string\[] \| number\[] | \[] | |
| disabled | whether disabled the tree | bool | false | |
| draggable | Specifies whether this Tree is draggable (IE > 8) | boolean | false | |
| expandedKeys(.sync) | (Controlled) Specifies the keys of the expanded treeNodes | string\[] \| number\[] | \[] | |
| filterTreeNode | Defines a function to filter (highlight) treeNodes. When the function returns `true`, the corresponding treeNode will be highlighted | function(node) | - | |
| loadData | Load data asynchronously | function(node) | - | |
| loadedKeys | (Controlled) Set loaded tree nodes. Need work with `loadData` | string\[] \| number\[] | \[] | |
| multiple | Allows selecting multiple treeNodes | boolean | false | |
| selectable | whether can be selected | boolean | true | |
| selectedKeys(.sync) | (Controlled) Specifies the keys of the selected treeNodes | string\[] \| number\[] | - | |
| showIcon | Shows the icon before a TreeNode's title. There is no default style; you must set a custom style for it if set to `true` | boolean | false | |
| switcherIcon | customize collapse/expand icon of tree node | slot | - | |
| showLine | Shows a connecting line | boolean | false | |
### Events
@ -47,20 +49,21 @@
One of the Tree `treeNode` prop for describing the tree's node, TreeNode has the same API.
| Property | Description | Type | Default |
| --- | --- | --- | --- |
| class | className | string | - |
| style | style | string\|object | - |
| disableCheckbox | Disables the checkbox of the treeNode | boolean | false |
| disabled | Disables the treeNode | boolean | false |
| icon | customize icon. When you pass component, whose render will receive full TreeNode props as component props | slot\|slot-scope | - |
| isLeaf | Determines if this is a leaf node(effective when `loadData` is specified) | boolean | false |
| key | Used with (default)ExpandedKeys / (default)CheckedKeys / (default)SelectedKeys. P.S.: It must be unique in all of treeNodes of the tree! | string \| number | internal calculated position of treeNode |
| selectable | Set whether the treeNode can be selected | boolean | true |
| title | Title | string\|slot\|slot-scope | '---' |
| slots | When using treeNodes, you can use this property to configure the properties that support the slot, such as `slots: { title: 'XXX'}` | object | - |
| scopedSlots | When using treeNodes, you can use this property to configure the properties that support the slot-scope, such as `scopedSlots: { title: 'XXX'}` | object | - |
| on | When using treeNodes, you can use this property to configure the events, such as `on: { click: () => {}}` | object | - |
| Property | Description | Type | Default | Version |
| --- | --- | --- | --- | --- |
| class | className | string | - | |
| style | style | string\|object | - | |
| checkable | When Tree is checkable, set TreeNode display Checkbox or not | boolean | - | 1.5.0 |
| disableCheckbox | Disables the checkbox of the treeNode | boolean | false | |
| disabled | Disables the treeNode | boolean | false | |
| icon | customize icon. When you pass component, whose render will receive full TreeNode props as component props | slot\|slot-scope | - | |
| isLeaf | Determines if this is a leaf node(effective when `loadData` is specified) | boolean | false | |
| key | Used with (default)ExpandedKeys / (default)CheckedKeys / (default)SelectedKeys. P.S.: It must be unique in all of treeNodes of the tree! | string \| number | internal calculated position of treeNode | |
| selectable | Set whether the treeNode can be selected | boolean | true | |
| title | Title | string\|slot\|slot-scope | '---' | |
| slots | When using treeNodes, you can use this property to configure the properties that support the slot, such as `slots: { title: 'XXX'}` | object | - | |
| scopedSlots | When using treeNodes, you can use this property to configure the properties that support the slot-scope, such as `scopedSlots: { title: 'XXX'}` | object | - | |
| on | When using treeNodes, you can use this property to configure the events, such as `on: { click: () => {}}` | object | - | |
### DirectoryTree props

View File

@ -2,30 +2,32 @@
### Tree props
| 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| treeData | 节点的配置描述,具体项见下表, 1.1.4 之前的版本使用`treeNodes` | array | -- |
| replaceFields | 替换 treeNode 中 title,key,children 字段为 treeData 中对应的字段 | object | {children:'children', title:'title', key:'key' } |
| autoExpandParent | 是否自动展开父节点 | boolean | true |
| checkable | 节点前添加 Checkbox 复选框 | boolean | false |
| checkedKeys(v-model) | (受控)选中复选框的树节点(注意:父子节点有关联,如果传入父节点 key则子节点自动选中相应当子节点 key 都传入,父节点也自动选中。当设置`checkable`和`checkStrictly`,它是一个有`checked`和`halfChecked`属性的对象,并且父子节点的选中与否不再关联 | string\[] \| number\[] \| {checked: string\[] \| number\[], halfChecked: string\[] \| number\[]} | \[] |
| checkStrictly | checkable 状态下节点选择完全受控(父子节点选中状态不再关联) | boolean | false |
| defaultCheckedKeys | 默认选中复选框的树节点 | string\[] \| number\[] | \[] |
| defaultExpandAll | 默认展开所有树节点 | boolean | false |
| defaultExpandedKeys | 默认展开指定的树节点 | string\[] \| number\[] | \[] |
| defaultExpandParent | 默认展开父节点 | bool | true |
| defaultSelectedKeys | 默认选中的树节点 | string\[] \| number\[] | \[] |
| disabled | 将树禁用 | bool | false |
| draggable | 设置节点可拖拽 | boolean | false |
| expandedKeys(.sync) | (受控)展开指定的树节点 | string\[] \| number\[] | \[] |
| filterTreeNode | 按需筛选树节点(高亮),返回 true | function(node) | - |
| loadData | 异步加载数据 | function(node) | - |
| loadedKeys | (受控)已经加载的节点,需要配合 `loadData` 使用 | string\[] \| number\[] | \[] |
| multiple | 支持点选多个节点(节点本身) | boolean | false |
| selectedKeys(.sync) | (受控)设置选中的树节点 | string\[] \| number\[] | - |
| showIcon | 是否展示 TreeNode title 前的图标,没有默认样式,如设置为 true需要自行定义图标相关样式 | boolean | false |
| switcherIcon | 自定义树节点的展开/折叠图标 | slot | - |
| showLine | 是否展示连接线 | boolean | false |
| 参数 | 说明 | 类型 | 默认值 | 版本 |
| --- | --- | --- | --- | --- |
| blockNode | 是否节点占据一行 | boolean | false | 1.5.0 |
| treeData | treeNodes 数据,如果设置则不需要手动构造 TreeNode 节点key 在整个树范围内唯一) | array\<{key, title, children, \[disabled, selectable]}> | -- | |
| replaceFields | 替换 treeNode 中 title,key,children 字段为 treeData 中对应的字段 | object | {children:'children', title:'title', key:'key' } | |
| autoExpandParent | 是否自动展开父节点 | boolean | true | |
| checkable | 节点前添加 Checkbox 复选框 | boolean | false | |
| checkedKeys(v-model) | (受控)选中复选框的树节点(注意:父子节点有关联,如果传入父节点 key则子节点自动选中相应当子节点 key 都传入,父节点也自动选中。当设置`checkable`和`checkStrictly`,它是一个有`checked`和`halfChecked`属性的对象,并且父子节点的选中与否不再关联 | string\[] \| number\[] \| {checked: string\[] \| number\[], halfChecked: string\[] \| number\[]} | \[] | |
| checkStrictly | checkable 状态下节点选择完全受控(父子节点选中状态不再关联) | boolean | false | |
| defaultCheckedKeys | 默认选中复选框的树节点 | string\[] \| number\[] | \[] | |
| defaultExpandAll | 默认展开所有树节点 | boolean | false | |
| defaultExpandedKeys | 默认展开指定的树节点 | string\[] \| number\[] | \[] | |
| defaultExpandParent | 默认展开父节点 | bool | true | |
| defaultSelectedKeys | 默认选中的树节点 | string\[] \| number\[] | \[] | |
| disabled | 将树禁用 | bool | false | |
| draggable | 设置节点可拖拽 | boolean | false | |
| expandedKeys(.sync) | (受控)展开指定的树节点 | string\[] \| number\[] | \[] | |
| filterTreeNode | 按需筛选树节点(高亮),返回 true | function(node) | - | |
| loadData | 异步加载数据 | function(node) | - | |
| loadedKeys | (受控)已经加载的节点,需要配合 `loadData` 使用 | string\[] \| number\[] | \[] | |
| multiple | 支持点选多个节点(节点本身) | boolean | false | |
| selectable | 是否可选中 | boolean | true | | |
| selectedKeys(.sync) | (受控)设置选中的树节点 | string\[] \| number\[] | - | |
| showIcon | 是否展示 TreeNode title 前的图标,没有默认样式,如设置为 true需要自行定义图标相关样式 | boolean | false | |
| switcherIcon | 自定义树节点的展开/折叠图标 | slot | - | |
| showLine | 是否展示连接线 | boolean | false | |
### 事件
@ -47,20 +49,21 @@
结点描述数据对象,是 treeNodes 中的一项TreeNode 使用相同的 API。
| 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| class | 节点的 class | string | - |
| style | 节点的 style | string\|object | - |
| disableCheckbox | 禁掉 checkbox | boolean | false |
| disabled | 禁掉响应 | boolean | false |
| icon | 自定义图标。可接收组件props 为当前节点 props | slot\|slot-scope | - |
| isLeaf | 设置为叶子节点(设置了`loadData`时有效) | boolean | false |
| key | 被树的 (default)ExpandedKeys / (default)CheckedKeys / (default)SelectedKeys 属性所用。注意:整个树范围内的所有节点的 key 值不能重复! | string \| number | 内部计算出的节点位置 |
| selectable | 设置节点是否可被选中 | boolean | true |
| title | 标题 | string\|slot\|slot-scope | '---' |
| slots | 使用 treeNodes 时,可以通过该属性配置支持 slot 的属性,如 `slots: { title: 'XXX'}` | object | - |
| scopedSlots | 使用 columns 时,可以通过该属性配置支持 slot-scope 的属性,如 `scopedSlots: { title: 'XXX'}` | object | - |
| on | 事件对象,仅在 treeNodes 使用方式中生效,如`{click: () => {}}` | object | '---' |
| 参数 | 说明 | 类型 | 默认值 | 版本 |
| --- | --- | --- | --- | --- |
| class | 节点的 class | string | - | |
| style | 节点的 style | string\|object | - | |
| checkable | 当树为 checkable 时,设置独立节点是否展示 Checkbox | boolean | - | 1.5.0 |
| disableCheckbox | 禁掉 checkbox | boolean | false | |
| disabled | 禁掉响应 | boolean | false | |
| icon | 自定义图标。可接收组件props 为当前节点 props | slot\|slot-scope | - | |
| isLeaf | 设置为叶子节点(设置了`loadData`时有效) | boolean | false | |
| key | 被树的 (default)ExpandedKeys / (default)CheckedKeys / (default)SelectedKeys 属性所用。注意:整个树范围内的所有节点的 key 值不能重复! | string \| number | 内部计算出的节点位置 | |
| selectable | 设置节点是否可被选中 | boolean | true | |
| title | 标题 | string\|slot\|slot-scope | '---' | |
| slots | 使用 treeNodes 时,可以通过该属性配置支持 slot 的属性,如 `slots: { title: 'XXX'}` | object | - | |
| scopedSlots | 使用 columns 时,可以通过该属性配置支持 slot-scope 的属性,如 `scopedSlots: { title: 'XXX'}` | object | - | |
| on | 事件对象,仅在 treeNodes 使用方式中生效,如`{click: () => {}}` | object | '---' | |
### DirectoryTree props

View File

@ -14,7 +14,7 @@ function traverseNodesKey(rootChildren, callback) {
function processNode(node) {
const { key } = node;
const children = getSlots(node).default;
if (callback(key) !== false) {
if (callback(key, node) !== false) {
traverseNodesKey(typeof children === 'function' ? children() : children, callback);
}
}
@ -72,3 +72,30 @@ export function calcRangeKeys(rootChildren, expandedKeys, startKey, endKey) {
return keys;
}
export function convertDirectoryKeysToNodes(rootChildren, keys) {
const restKeys = [...keys];
const nodes = [];
traverseNodesKey(rootChildren, (key, node) => {
const index = restKeys.indexOf(key);
if (index !== -1) {
nodes.push(node);
restKeys.splice(index, 1);
}
return !!restKeys.length;
});
return nodes;
}
export function getFullKeyListByTreeData(treeData) {
let keys = [];
(treeData || []).forEach(item => {
keys.push(item.key);
if (item.children) {
keys = [...keys, ...getFullKeyListByTreeData(item.children)];
}
});
return keys;
}

View File

@ -46,7 +46,6 @@ const TreeNode = {
icon: PropTypes.any,
dataRef: PropTypes.object,
switcherIcon: PropTypes.any,
label: PropTypes.any,
value: PropTypes.any,
},
@ -416,7 +415,8 @@ const TreeNode = {
// Icon + Title
renderSelector(h) {
const { selected, icon, loading, dragNodeHighlight } = this;
const { selected, loading, dragNodeHighlight } = this;
const icon = getComponentFromProp(this, 'icon');
const {
vcTree: { prefixCls, showIcon, icon: treeIcon, draggable, loadData },
} = this;

View File

@ -34,7 +34,7 @@ const isGitee = window.location.host.indexOf('gitee.io') > -1;
enquireScreen(b => {
isMobile = b;
});
const showAd = location.host.indexOf('antdv.com') > -1;
export default {
props: {
name: String,
@ -296,9 +296,9 @@ export default {
)}
<a-col xxl={20} xl={19} lg={19} md={18} sm={24} xs={24}>
<section class="main-container main-container-component">
<GoogleAdsTop key={`GoogleAdsTop_${$route.path}`} />
{showAd ? <GoogleAdsTop key={`GoogleAdsTop_${$route.path}`} /> : null}
{!isMobile ? <CarbonAds /> : null}
<GeektimeAds isMobile={isMobile} />
{showAd ? <GeektimeAds isMobile={isMobile} /> : null}
{!isMobile ? (
<div class={['toc-affix', isCN ? 'toc-affix-cn' : '']} style="width: 150px;">
{this.getSubMenu(isCN)}

16
types/tree/tree.d.ts vendored
View File

@ -1,6 +1,6 @@
// Project: https://github.com/vueComponent/ant-design-vue
// Definitions by: akki-jat <https://github.com/akki-jat>
// Definitions: https://github.com/vueComponent/ant-design-vue/types
// Project: https://github.com/vueComponent/ant-design-vue Definitions by:
// akki-jat <https://github.com/akki-jat> Definitions:
// https://github.com/vueComponent/ant-design-vue/types
import { AntdComponent } from '../component';
import { TreeNode } from '../tree-node';
@ -10,6 +10,8 @@ export declare class Tree extends AntdComponent {
static TreeNode: typeof TreeNode;
static DirectoryTree: typeof DictionaryTree;
blockNode: boolean;
selectable: boolean;
/**
* treeNode of tree
* @type TreeNode[]
@ -54,7 +56,13 @@ export declare class Tree extends AntdComponent {
* @default []
* @type string[] | number[] | { checked: string[]; halfChecked: string[] }
*/
checkedKeys: string[] | number[] | { checked: string[]; halfChecked: string[] };
checkedKeys:
| string[]
| number[]
| {
checked: string[];
halfChecked: string[];
};
/**
* Check treeNode precisely; parent treeNode and children treeNodes are not associated