parent
00455da385
commit
de05f936c1
|
@ -165,7 +165,7 @@ const Menu = defineComponent({
|
|||
|
||||
// Fix SVGElement e.target.className.indexOf is not a function
|
||||
// https://github.com/ant-design/ant-design/issues/15699
|
||||
const { className } = e.target as (SVGAnimationElement | HTMLElement);
|
||||
const { className } = e.target as SVGAnimationElement | HTMLElement;
|
||||
// SVGAnimatedString.animVal should be identical to SVGAnimatedString.baseVal, unless during an animation.
|
||||
const classNameValue =
|
||||
Object.prototype.toString.call(className) === '[object SVGAnimatedString]'
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { defineComponent, inject } from 'vue';
|
||||
import { defineComponent, inject, VNode } from 'vue';
|
||||
import omit from 'omit.js';
|
||||
import debounce from 'lodash-es/debounce';
|
||||
import FolderOpenOutlined from '@ant-design/icons-vue/FolderOpenOutlined';
|
||||
|
@ -7,7 +7,7 @@ import FileOutlined from '@ant-design/icons-vue/FileOutlined';
|
|||
import PropTypes from '../_util/vue-types';
|
||||
import classNames from '../_util/classNames';
|
||||
import { conductExpandParent, convertTreeToEntities } from '../vc-tree/src/util';
|
||||
import Tree, { TreeProps } from './Tree';
|
||||
import Tree, { CheckEvent, ExpendEvent, SelectEvent, TreeProps } from './Tree';
|
||||
import {
|
||||
calcRangeKeys,
|
||||
getFullKeyList,
|
||||
|
@ -25,11 +25,11 @@ import { defaultConfigProvider } from '../config-provider';
|
|||
// selectedKeys?: string[]; }
|
||||
|
||||
export interface DirectoryTreeState {
|
||||
_expandedKeys?: string[];
|
||||
_selectedKeys?: string[];
|
||||
_expandedKeys?: (string | number)[];
|
||||
_selectedKeys?: (string | number)[];
|
||||
}
|
||||
|
||||
function getIcon(props) {
|
||||
function getIcon(props: { isLeaf: boolean; expanded: boolean } & VNode) {
|
||||
const { isLeaf, expanded } = props;
|
||||
if (isLeaf) {
|
||||
return <FileOutlined />;
|
||||
|
@ -56,7 +56,7 @@ export default defineComponent({
|
|||
children: null,
|
||||
onDebounceExpand: null,
|
||||
tree: null,
|
||||
lastSelectedKey: [],
|
||||
lastSelectedKey: '',
|
||||
cachedSelectedKeys: [],
|
||||
configProvider: inject('configProvider', defaultConfigProvider),
|
||||
};
|
||||
|
@ -100,7 +100,7 @@ export default defineComponent({
|
|||
this.onDebounceExpand = debounce(this.expandFolderNode, 200, { leading: true });
|
||||
},
|
||||
methods: {
|
||||
handleExpand(expandedKeys, info) {
|
||||
handleExpand(expandedKeys: (string | number)[], info: ExpendEvent) {
|
||||
this.setUncontrolledState({ _expandedKeys: expandedKeys });
|
||||
this.$emit('update:expandedKeys', expandedKeys);
|
||||
this.$emit('expand', expandedKeys, info);
|
||||
|
@ -108,7 +108,7 @@ export default defineComponent({
|
|||
return undefined;
|
||||
},
|
||||
|
||||
handleClick(event, node) {
|
||||
handleClick(event: MouseEvent, node: VNode) {
|
||||
const { expandAction } = this.$props;
|
||||
|
||||
// Expand the tree
|
||||
|
@ -118,7 +118,7 @@ export default defineComponent({
|
|||
this.$emit('click', event, node);
|
||||
},
|
||||
|
||||
handleDoubleClick(event, node) {
|
||||
handleDoubleClick(event: MouseEvent, node: VNode) {
|
||||
const { expandAction } = this.$props;
|
||||
|
||||
// Expand the tree
|
||||
|
@ -130,7 +130,7 @@ export default defineComponent({
|
|||
this.$emit('dblclick', event, node);
|
||||
},
|
||||
|
||||
hanldeSelect(keys, event) {
|
||||
hanldeSelect(keys: (string | number)[], event: SelectEvent) {
|
||||
const { multiple } = this.$props;
|
||||
const children = this.children || [];
|
||||
const { _expandedKeys: expandedKeys = [] } = this.$data;
|
||||
|
@ -150,7 +150,7 @@ export default defineComponent({
|
|||
const shiftPick = nativeEvent.shiftKey;
|
||||
|
||||
// Generate new selected keys
|
||||
let newSelectedKeys;
|
||||
let newSelectedKeys: (string | number)[];
|
||||
if (multiple && ctrlPick) {
|
||||
// Control click
|
||||
newSelectedKeys = keys;
|
||||
|
@ -180,11 +180,11 @@ export default defineComponent({
|
|||
|
||||
this.setUncontrolledState(newState);
|
||||
},
|
||||
setTreeRef(node) {
|
||||
setTreeRef(node: VNode) {
|
||||
this.tree = node;
|
||||
},
|
||||
|
||||
expandFolderNode(event, node) {
|
||||
expandFolderNode(event: MouseEvent, node: { isLeaf: boolean } & VNode) {
|
||||
const { isLeaf } = node;
|
||||
|
||||
if (isLeaf || event.shiftKey || event.metaKey || event.ctrlKey) {
|
||||
|
@ -201,7 +201,7 @@ export default defineComponent({
|
|||
}
|
||||
},
|
||||
|
||||
setUncontrolledState(state) {
|
||||
setUncontrolledState(state: unknown) {
|
||||
const newState = omit(
|
||||
state,
|
||||
Object.keys(getOptionProps(this)).map(p => `_${p}`),
|
||||
|
@ -210,7 +210,7 @@ export default defineComponent({
|
|||
this.setState(newState);
|
||||
}
|
||||
},
|
||||
handleCheck(checkedObj, eventObj) {
|
||||
handleCheck(checkedObj: (string | number)[], eventObj: CheckEvent) {
|
||||
this.$emit('update:checkedKeys', checkedObj);
|
||||
this.$emit('check', checkedObj, eventObj);
|
||||
},
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { defineComponent, inject } from 'vue';
|
||||
import { defineComponent, inject, VNode, PropType } from 'vue';
|
||||
import classNames from '../_util/classNames';
|
||||
import LoadingOutlined from '@ant-design/icons-vue/LoadingOutlined';
|
||||
import FileOutlined from '@ant-design/icons-vue/FileOutlined';
|
||||
|
@ -14,6 +14,46 @@ import { cloneElement } from '../_util/vnode';
|
|||
import { defaultConfigProvider } from '../config-provider';
|
||||
|
||||
const TreeNode = VcTree.TreeNode;
|
||||
|
||||
export interface TreeDataItem {
|
||||
key?: string | number;
|
||||
title?: string;
|
||||
isLeaf?: boolean;
|
||||
selectable?: boolean;
|
||||
children?: TreeDataItem[];
|
||||
disableCheckbox?: boolean;
|
||||
disabled?: boolean;
|
||||
class?: string;
|
||||
style?: any;
|
||||
checkable?: boolean;
|
||||
icon?: any;
|
||||
slots?: any;
|
||||
switcherIcon?: any;
|
||||
}
|
||||
|
||||
interface DefaultEvent {
|
||||
nativeEvent: MouseEvent;
|
||||
node: any;
|
||||
}
|
||||
|
||||
export interface CheckEvent extends DefaultEvent {
|
||||
checked: boolean;
|
||||
checkedNodes: VNode[];
|
||||
checkedNodesPositions: { node: VNode; pos: string | number }[];
|
||||
event: string;
|
||||
halfCheckedKeys: (string | number)[];
|
||||
}
|
||||
|
||||
export interface ExpendEvent extends DefaultEvent {
|
||||
expanded: boolean;
|
||||
}
|
||||
|
||||
export interface SelectEvent extends DefaultEvent {
|
||||
event: string;
|
||||
selected: boolean;
|
||||
selectedNodes: VNode[];
|
||||
}
|
||||
|
||||
function TreeProps() {
|
||||
return {
|
||||
showLine: PropTypes.looseBool,
|
||||
|
@ -32,30 +72,36 @@ function TreeProps() {
|
|||
/** 默认展开对应树节点 */
|
||||
defaultExpandParent: PropTypes.looseBool,
|
||||
/** 默认展开指定的树节点 */
|
||||
defaultExpandedKeys: PropTypes.array,
|
||||
defaultExpandedKeys: PropTypes.arrayOf(
|
||||
PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
||||
),
|
||||
/** (受控)展开指定的树节点 */
|
||||
expandedKeys: PropTypes.array,
|
||||
expandedKeys: PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.string, PropTypes.number])),
|
||||
/** (受控)选中复选框的树节点 */
|
||||
checkedKeys: PropTypes.oneOfType([
|
||||
PropTypes.array,
|
||||
PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.string, PropTypes.number])),
|
||||
PropTypes.shape({
|
||||
checked: PropTypes.array,
|
||||
halfChecked: PropTypes.array,
|
||||
checked: PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.string, PropTypes.number])),
|
||||
halfChecked: PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.string, PropTypes.number])),
|
||||
}).loose,
|
||||
]),
|
||||
/** 默认选中复选框的树节点 */
|
||||
defaultCheckedKeys: PropTypes.array,
|
||||
defaultCheckedKeys: PropTypes.arrayOf(
|
||||
PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
||||
),
|
||||
/** (受控)设置选中的树节点 */
|
||||
selectedKeys: PropTypes.array,
|
||||
selectedKeys: PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.string, PropTypes.number])),
|
||||
/** 默认选中的树节点 */
|
||||
defaultSelectedKeys: PropTypes.array,
|
||||
defaultSelectedKeys: PropTypes.arrayOf(
|
||||
PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
||||
),
|
||||
selectable: PropTypes.looseBool,
|
||||
|
||||
/** filter some AntTreeNodes as you need. it should return true */
|
||||
filterAntTreeNode: PropTypes.func,
|
||||
/** 异步加载数据 */
|
||||
loadData: PropTypes.func,
|
||||
loadedKeys: PropTypes.array,
|
||||
loadedKeys: PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.string, PropTypes.number])),
|
||||
// onLoaded: (loadedKeys: string[], info: { event: 'load', node: AntTreeNode; }) => void,
|
||||
/** 响应右键点击 */
|
||||
// onRightClick: (options: AntTreeNodeMouseEvent) => void,
|
||||
|
@ -77,7 +123,9 @@ function TreeProps() {
|
|||
prefixCls: PropTypes.string,
|
||||
filterTreeNode: PropTypes.func,
|
||||
openAnimation: PropTypes.any,
|
||||
treeData: PropTypes.array,
|
||||
treeData: {
|
||||
type: Array as PropType<TreeDataItem[]>,
|
||||
},
|
||||
/**
|
||||
* @default{title,key,children}
|
||||
* 替换treeNode中 title,key,children字段为treeData中对应的字段
|
||||
|
@ -123,7 +171,7 @@ export default defineComponent({
|
|||
},
|
||||
TreeNode,
|
||||
methods: {
|
||||
renderSwitcherIcon(prefixCls: string, switcherIcon, { isLeaf, loading, expanded }) {
|
||||
renderSwitcherIcon(prefixCls: string, switcherIcon: VNode, { isLeaf, loading, expanded }) {
|
||||
const { showLine } = this.$props;
|
||||
if (loading) {
|
||||
return <LoadingOutlined class={`${prefixCls}-switcher-loading-icon`} />;
|
||||
|
@ -148,26 +196,19 @@ export default defineComponent({
|
|||
<CaretDownFilled class={switcherCls} />
|
||||
);
|
||||
},
|
||||
updateTreeData(treeData) {
|
||||
updateTreeData(treeData: TreeDataItem[]) {
|
||||
const { $slots } = this;
|
||||
const defaultFields = { children: 'children', title: 'title', key: 'key' };
|
||||
const replaceFields = { ...defaultFields, ...this.$props.replaceFields };
|
||||
return treeData.map(item => {
|
||||
const key = item[replaceFields.key];
|
||||
const children = item[replaceFields.children];
|
||||
const { slots = {}, scopedSlots = {}, class: cls, style, ...restProps } = item;
|
||||
const { slots = {}, class: cls, style, ...restProps } = item;
|
||||
const treeNodeProps = {
|
||||
...restProps,
|
||||
icon: $slots[scopedSlots.icon] || $slots[slots.icon] || restProps.icon,
|
||||
switcherIcon:
|
||||
$slots[scopedSlots.switcherIcon] ||
|
||||
$slots[slots.switcherIcon] ||
|
||||
restProps.switcherIcon,
|
||||
title:
|
||||
$slots[scopedSlots.title] ||
|
||||
$slots[slots.title] ||
|
||||
$slots.title ||
|
||||
restProps[replaceFields.title],
|
||||
icon: $slots[slots.icon] || restProps.icon,
|
||||
switcherIcon: $slots[slots.switcherIcon] || restProps.switcherIcon,
|
||||
title: $slots[slots.title] || $slots.title || restProps[replaceFields.title],
|
||||
dataRef: item,
|
||||
key,
|
||||
class: cls,
|
||||
|
@ -179,18 +220,18 @@ export default defineComponent({
|
|||
return treeNodeProps;
|
||||
});
|
||||
},
|
||||
setTreeRef(node) {
|
||||
setTreeRef(node: VNode) {
|
||||
this.tree = node;
|
||||
},
|
||||
handleCheck(checkedObj, eventObj) {
|
||||
handleCheck(checkedObj: (number | string)[], eventObj: CheckEvent) {
|
||||
this.$emit('update:checkedKeys', checkedObj);
|
||||
this.$emit('check', checkedObj, eventObj);
|
||||
},
|
||||
handleExpand(expandedKeys, eventObj) {
|
||||
handleExpand(expandedKeys: (number | string)[], eventObj: ExpendEvent) {
|
||||
this.$emit('update:expandedKeys', expandedKeys);
|
||||
this.$emit('expand', expandedKeys, eventObj);
|
||||
},
|
||||
handleSelect(selectedKeys: string[], eventObj) {
|
||||
handleSelect(selectedKeys: (number | string)[], eventObj: SelectEvent) {
|
||||
this.$emit('update:selectedKeys', selectedKeys);
|
||||
this.$emit('select', selectedKeys, eventObj);
|
||||
},
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
import { VNode } from 'vue';
|
||||
import { getNodeChildren, convertTreeToEntities } from '../vc-tree/src/util';
|
||||
import { getSlot } from '../_util/props-util';
|
||||
import { TreeDataItem } from './Tree';
|
||||
|
||||
enum Record {
|
||||
None,
|
||||
|
@ -7,11 +9,13 @@ enum Record {
|
|||
End,
|
||||
}
|
||||
|
||||
type TreeKey = string | number;
|
||||
|
||||
// TODO: Move this logic into `rc-tree`
|
||||
function traverseNodesKey(rootChildren, callback) {
|
||||
function traverseNodesKey(rootChildren: VNode[], callback?: Function) {
|
||||
const nodeList = getNodeChildren(rootChildren) || [];
|
||||
|
||||
function processNode(node) {
|
||||
function processNode(node: VNode) {
|
||||
const { key } = node;
|
||||
const children = getSlot(node);
|
||||
if (callback(key, node) !== false) {
|
||||
|
@ -22,13 +26,18 @@ function traverseNodesKey(rootChildren, callback) {
|
|||
nodeList.forEach(processNode);
|
||||
}
|
||||
|
||||
export function getFullKeyList(children) {
|
||||
export function getFullKeyList(children: VNode[]) {
|
||||
const { keyEntities } = convertTreeToEntities(children);
|
||||
return [...keyEntities.keys()];
|
||||
}
|
||||
|
||||
/** 计算选中范围,只考虑expanded情况以优化性能 */
|
||||
export function calcRangeKeys(rootChildren, expandedKeys, startKey, endKey) {
|
||||
export function calcRangeKeys(
|
||||
rootChildren: VNode[],
|
||||
expandedKeys: TreeKey[],
|
||||
startKey: TreeKey,
|
||||
endKey: TreeKey,
|
||||
) {
|
||||
const keys = [];
|
||||
let record = Record.None;
|
||||
|
||||
|
@ -39,11 +48,11 @@ export function calcRangeKeys(rootChildren, expandedKeys, startKey, endKey) {
|
|||
return [];
|
||||
}
|
||||
|
||||
function matchKey(key) {
|
||||
function matchKey(key: TreeKey) {
|
||||
return key === startKey || key === endKey;
|
||||
}
|
||||
|
||||
traverseNodesKey(rootChildren, key => {
|
||||
traverseNodesKey(rootChildren, (key: TreeKey) => {
|
||||
if (record === Record.End) {
|
||||
return false;
|
||||
}
|
||||
|
@ -73,10 +82,10 @@ export function calcRangeKeys(rootChildren, expandedKeys, startKey, endKey) {
|
|||
return keys;
|
||||
}
|
||||
|
||||
export function convertDirectoryKeysToNodes(rootChildren, keys) {
|
||||
export function convertDirectoryKeysToNodes(rootChildren: VNode[], keys: TreeKey[]) {
|
||||
const restKeys = [...keys];
|
||||
const nodes = [];
|
||||
traverseNodesKey(rootChildren, (key, node) => {
|
||||
traverseNodesKey(rootChildren, (key: TreeKey, node: VNode) => {
|
||||
const index = restKeys.indexOf(key);
|
||||
if (index !== -1) {
|
||||
nodes.push(node);
|
||||
|
@ -88,13 +97,15 @@ export function convertDirectoryKeysToNodes(rootChildren, keys) {
|
|||
return nodes;
|
||||
}
|
||||
|
||||
export function getFullKeyListByTreeData(treeData: any, replaceFields: any = {}) {
|
||||
export function getFullKeyListByTreeData(treeData: TreeDataItem[], replaceFields: any = {}) {
|
||||
let keys = [];
|
||||
const { key = 'key', children = 'children' } = replaceFields(treeData || []).forEach(item => {
|
||||
keys.push(item[key]);
|
||||
if (item[children]) {
|
||||
keys = [...keys, ...getFullKeyListByTreeData(item[children], replaceFields)];
|
||||
}
|
||||
});
|
||||
const { key = 'key', children = 'children' } = replaceFields(treeData || []).forEach(
|
||||
(item: TreeDataItem) => {
|
||||
keys.push(item[key]);
|
||||
if (item[children]) {
|
||||
keys = [...keys, ...getFullKeyListByTreeData(item[children], replaceFields)];
|
||||
}
|
||||
},
|
||||
);
|
||||
return keys;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue