ant-design-vue/components/tree/Tree.jsx

218 lines
7.4 KiB
Vue
Raw Normal View History

2019-01-12 11:33:27 +08:00
import warning from 'warning';
import { Tree as VcTree, TreeNode } from '../vc-tree';
import animation from '../_util/openAnimation';
import PropTypes from '../_util/vue-types';
2019-05-28 11:37:38 +08:00
import {
initDefaultProps,
getOptionProps,
filterEmpty,
getComponentFromProp,
getClass,
} from '../_util/props-util';
2019-04-10 13:28:07 +08:00
import { cloneElement } from '../_util/vnode';
import { ConfigConsumerProps } from '../config-provider';
2019-01-12 11:33:27 +08:00
import Icon from '../icon';
2018-09-26 22:57:01 +08:00
2019-01-12 11:33:27 +08:00
function TreeProps() {
2018-09-26 22:57:01 +08:00
return {
showLine: PropTypes.bool,
/** 是否支持多选 */
multiple: PropTypes.bool,
/** 是否自动展开父节点 */
autoExpandParent: PropTypes.bool,
/** checkable状态下节点选择完全受控父子节点选中状态不再关联*/
checkStrictly: PropTypes.bool,
/** 是否支持选中 */
checkable: PropTypes.bool,
/** 是否禁用树 */
disabled: PropTypes.bool,
/** 默认展开所有树节点 */
defaultExpandAll: PropTypes.bool,
/** 默认展开对应树节点 */
defaultExpandParent: PropTypes.bool,
/** 默认展开指定的树节点 */
defaultExpandedKeys: PropTypes.array,
2018-09-26 22:57:01 +08:00
/** (受控)展开指定的树节点 */
expandedKeys: PropTypes.array,
2018-09-26 22:57:01 +08:00
/** (受控)选中复选框的树节点 */
2019-01-12 11:33:27 +08:00
checkedKeys: PropTypes.oneOfType([
PropTypes.array,
PropTypes.shape({
checked: PropTypes.array,
halfChecked: PropTypes.array,
}).loose,
]),
2018-09-26 22:57:01 +08:00
/** 默认选中复选框的树节点 */
defaultCheckedKeys: PropTypes.array,
2018-09-26 22:57:01 +08:00
/** (受控)设置选中的树节点 */
selectedKeys: PropTypes.array,
2018-09-26 22:57:01 +08:00
/** 默认选中的树节点 */
defaultSelectedKeys: PropTypes.array,
2018-09-26 22:57:01 +08:00
selectable: PropTypes.bool,
/** 展开/收起节点时触发 */
// onExpand: (expandedKeys: string[], info: AntTreeNodeExpandedEvent) => void | PromiseLike<any>,
/** 点击复选框触发 */
// onCheck: (checkedKeys: string[] | { checked: string[]; halfChecked: string[] }, e: AntTreeNodeCheckedEvent) => void,
/** 点击树节点触发 */
// onSelect: (selectedKeys: string[], e: AntTreeNodeSelectedEvent) => void,
/** 单击树节点触发 */
// onClick: (e: React.MouseEvent<HTMLElement>, node: AntTreeNode) => void,
/** 双击树节点触发 */
// onDoubleClick: (e: React.MouseEvent<HTMLElement>, node: AntTreeNode) => void,
/** filter some AntTreeNodes as you need. it should return true */
filterAntTreeNode: PropTypes.func,
/** 异步加载数据 */
loadData: PropTypes.func,
loadedKeys: PropTypes.array,
2018-09-26 22:57:01 +08:00
// onLoaded: (loadedKeys: string[], info: { event: 'load', node: AntTreeNode; }) => void,
/** 响应右键点击 */
// onRightClick: (options: AntTreeNodeMouseEvent) => void,
/** 设置节点可拖拽IE>8*/
draggable: PropTypes.bool,
// /** 开始拖拽时调用 */
// onDragStart: (options: AntTreeNodeMouseEvent) => void,
// /** dragenter 触发时调用 */
// onDragEnter: (options: AntTreeNodeMouseEvent) => void,
// /** dragover 触发时调用 */
// onDragOver: (options: AntTreeNodeMouseEvent) => void,
// /** dragleave 触发时调用 */
// onDragLeave: (options: AntTreeNodeMouseEvent) => void,
// /** drop 触发时调用 */
// onDrop: (options: AntTreeNodeMouseEvent) => void,
showIcon: PropTypes.bool,
icon: PropTypes.func,
2019-04-10 13:28:07 +08:00
switcherIcon: PropTypes.any,
2018-09-26 22:57:01 +08:00
prefixCls: PropTypes.string,
filterTreeNode: PropTypes.func,
openAnimation: PropTypes.any,
treeNodes: PropTypes.array,
treeData: PropTypes.array,
/**
* @default{title,key,children}
* 替换treeNode中 title,key,children字段为treeData中对应的字段
*/
replaceFields: PropTypes.object,
2019-01-12 11:33:27 +08:00
};
2018-09-26 22:57:01 +08:00
}
2019-01-12 11:33:27 +08:00
export { TreeProps };
2018-09-26 22:57:01 +08:00
export default {
name: 'ATree',
model: {
prop: 'checkedKeys',
event: 'check',
},
props: initDefaultProps(TreeProps(), {
checkable: false,
showIcon: false,
openAnimation: {
on: animation,
props: { appear: null },
},
}),
2019-04-10 13:28:07 +08:00
inject: {
2019-09-11 22:35:25 +08:00
configProvider: { default: () => ConfigConsumerProps },
2019-04-10 13:28:07 +08:00
},
2019-01-12 11:33:27 +08:00
created() {
2018-09-26 22:57:01 +08:00
warning(
!('treeNodes' in getOptionProps(this)),
2019-01-12 11:33:27 +08:00
'`treeNodes` is deprecated. please use treeData instead.',
);
2018-09-26 22:57:01 +08:00
},
TreeNode,
methods: {
2019-04-10 13:28:07 +08:00
renderSwitcherIcon(prefixCls, switcherIcon, { isLeaf, expanded, loading }) {
const { showLine } = this.$props;
2018-12-11 20:33:37 +08:00
if (loading) {
2019-01-12 11:33:27 +08:00
return <Icon type="loading" class={`${prefixCls}-switcher-loading-icon`} />;
2018-12-11 20:33:37 +08:00
}
if (showLine) {
if (isLeaf) {
2019-01-12 11:33:27 +08:00
return <Icon type="file" class={`${prefixCls}-switcher-line-icon`} />;
2018-12-11 20:33:37 +08:00
}
return (
<Icon
type={expanded ? 'minus-square' : 'plus-square'}
class={`${prefixCls}-switcher-line-icon`}
2019-01-12 11:33:27 +08:00
theme="outlined"
2018-12-11 20:33:37 +08:00
/>
2019-01-12 11:33:27 +08:00
);
2018-12-11 20:33:37 +08:00
} else {
2019-04-10 13:28:07 +08:00
const switcherCls = `${prefixCls}-switcher-icon`;
2018-12-11 20:33:37 +08:00
if (isLeaf) {
2019-01-12 11:33:27 +08:00
return null;
2019-05-28 11:37:38 +08:00
} else if (switcherIcon) {
2019-04-10 13:28:07 +08:00
const switcherOriginCls = getClass(switcherIcon[0]);
return cloneElement(switcherIcon, {
class: {
[switcherCls]: true,
},
});
} else {
return <Icon type="caret-down" class={`${prefixCls}-switcher-icon`} theme="filled" />;
2018-12-11 20:33:37 +08:00
}
}
},
2019-03-18 15:10:20 +08:00
updateTreeData(treeData) {
2019-01-12 11:33:27 +08:00
const { $slots, $scopedSlots } = this;
const defaultFields = { children: 'children', title: 'title', key: 'key' };
const replaceFields = { ...defaultFields, ...this.$props.replaceFields };
2019-01-12 11:33:27 +08:00
return treeData.map(item => {
const key = item[replaceFields.key];
const children = item[replaceFields.children];
2019-12-21 18:37:33 +08:00
const { on = {}, slots = {}, scopedSlots = {}, class: cls, style, ...restProps } = item;
2018-09-26 22:57:01 +08:00
const treeNodeProps = {
...restProps,
2019-01-12 11:33:27 +08:00
icon:
$slots[slots.icon] ||
($scopedSlots[scopedSlots.icon] && $scopedSlots[scopedSlots.icon](item)) ||
2019-01-12 11:33:27 +08:00
restProps.icon,
title:
$slots[slots.title] ||
($scopedSlots[scopedSlots.title] && $scopedSlots[scopedSlots.title](item)) ||
restProps[replaceFields.title],
2018-09-26 22:57:01 +08:00
dataRef: item,
on,
key,
class: cls,
style,
2019-01-12 11:33:27 +08:00
};
2018-09-26 22:57:01 +08:00
if (children) {
2019-03-18 15:10:20 +08:00
return { ...treeNodeProps, children: this.updateTreeData(children) };
2018-09-26 22:57:01 +08:00
}
2019-01-12 11:33:27 +08:00
return treeNodeProps;
});
2018-09-26 22:57:01 +08:00
},
},
2019-01-12 11:33:27 +08:00
render() {
const props = getOptionProps(this);
2019-04-10 13:28:07 +08:00
const { prefixCls: customizePrefixCls, showIcon, treeNodes } = props;
2019-09-11 22:35:25 +08:00
const getPrefixCls = this.configProvider.getPrefixCls;
2019-04-10 13:28:07 +08:00
const prefixCls = getPrefixCls('tree', customizePrefixCls);
const switcherIcon = getComponentFromProp(this, 'switcherIcon');
2019-01-12 11:33:27 +08:00
const checkable = props.checkable;
let treeData = props.treeData || treeNodes;
2018-09-26 22:57:01 +08:00
if (treeData) {
2019-03-18 15:10:20 +08:00
treeData = this.updateTreeData(treeData);
2018-09-26 22:57:01 +08:00
}
const vcTreeProps = {
props: {
...props,
2019-04-10 13:28:07 +08:00
prefixCls,
2018-09-26 22:57:01 +08:00
checkable: checkable ? <span class={`${prefixCls}-checkbox-inner`} /> : checkable,
children: filterEmpty(this.$slots.default || []),
2018-09-26 22:57:01 +08:00
__propsSymbol__: Symbol(),
2019-05-28 11:37:38 +08:00
switcherIcon: nodeProps => this.renderSwitcherIcon(prefixCls, switcherIcon, nodeProps),
2018-09-26 22:57:01 +08:00
},
on: this.$listeners,
2018-12-11 20:33:37 +08:00
ref: 'tree',
2018-09-26 22:57:01 +08:00
class: !showIcon && `${prefixCls}-icon-hide`,
2019-01-12 11:33:27 +08:00
};
2018-09-26 22:57:01 +08:00
if (treeData) {
2019-01-12 11:33:27 +08:00
vcTreeProps.props.treeData = treeData;
2018-09-26 22:57:01 +08:00
}
2019-01-12 11:33:27 +08:00
return <VcTree {...vcTreeProps} />;
2018-09-26 22:57:01 +08:00
},
2019-01-12 11:33:27 +08:00
};