Files
element-plus/packages/components/tree-v2/src/virtual-tree.ts
msidolphin 2d2878eb53 feat(components): add virtual tree (#3398)
* feat(components): add virtual tree

* perf: optimize compute performance

* perf: optimize update checked states performance

* feat(components): [tree-v2] supports filter method

* feat(components): [el-tree-v2] exposes check api

* feat(components): [el-tree-v2] exposes current api

* feat(components): [el-tree-v2] support contextmenu event

* style(components): [el-tree-v2] optimized code style

* refactor(components): [el-tree-v2] using svg icon

* refactor(components): [el-tree-v2] replace all PropType with buildProp

replace all PropType with buildProp, support perfMode, expose setData

* refactor: improve prop

* docs: [el-tree-v2] improve documention

* refactor(components): [el-tree-v2] optimized code

Co-authored-by: Kevin <sxzz@sxzz.moe>
2021-09-27 11:12:50 +08:00

183 lines
4.4 KiB
TypeScript

import { buildProp, definePropType, mutable } from '@element-plus/utils/props'
import type { InjectionKey } from 'vue'
import type { TreeNodeData } from '../../tree/src/tree.type'
import type {
TreeNode,
TreeKey,
TreeData,
TreeOptionProps,
FilterMethod,
CheckedInfo,
TreeContext,
} from './types'
// constants
export const ROOT_TREE_INJECTION_KEY: InjectionKey<TreeContext> = Symbol()
const EMPTY_NODE = {
key: -1,
level: -1,
data: {},
} as const
// enums
export enum TreeOptionsEnum {
KEY = 'id',
LABEL = 'label',
CHILDREN = 'children',
DISABLED = 'disabled',
}
export const enum SetOperationEnum {
ADD = 'add',
DELETE = 'delete',
}
// props
export const treeProps = {
data: buildProp({
type: definePropType<TreeData>(Array),
default: () => mutable([] as const),
} as const),
emptyText: buildProp({
type: String,
}),
height: buildProp({
type: Number,
default: 200,
}),
props: buildProp({
type: definePropType<TreeOptionProps>(Object),
default: () =>
mutable({
children: TreeOptionsEnum.CHILDREN,
label: TreeOptionsEnum.LABEL,
disabled: TreeOptionsEnum.DISABLED,
value: TreeOptionsEnum.KEY,
} as const),
} as const),
highlightCurrent: buildProp({
type: Boolean,
default: false,
}),
showCheckbox: buildProp({
type: Boolean,
default: false,
}),
defaultCheckedKeys: buildProp({
type: definePropType<TreeKey[]>(Array),
default: () => mutable([] as const),
} as const),
// Whether checked state of a node not affects its father and
// child nodes when show-checkbox is true
checkStrictly: buildProp({
type: Boolean,
default: false,
}),
defaultExpandedKeys: buildProp({
type: definePropType<TreeKey[]>(Array),
default: () => mutable([] as const),
} as const),
indent: buildProp({
type: Number,
default: 16,
}),
icon: buildProp({
type: String,
}),
expandOnClickNode: buildProp({
type: Boolean,
default: true,
}),
checkOnClickNode: buildProp({
type: Boolean,
default: false,
}),
currentNodeKey: buildProp({
type: definePropType<TreeKey>([String, Number]),
} as const),
// TODO need to optimization
accordion: buildProp({
type: Boolean,
default: false,
}),
filterMethod: buildProp({
type: definePropType<FilterMethod>(Function),
} as const),
// Performance mode will increase memory usage, but scrolling will be smoother
perfMode: buildProp({
type: Boolean,
default: true,
}),
} as const
export const treeNodeProps = {
node: buildProp({
type: definePropType<TreeNode>(Object),
default: () => mutable(EMPTY_NODE),
} as const),
expanded: buildProp({
type: Boolean,
default: false,
}),
checked: buildProp({
type: Boolean,
default: false,
}),
indeterminate: buildProp({
type: Boolean,
default: false,
}),
showCheckbox: buildProp({
type: Boolean,
default: false,
}),
disabled: buildProp({
type: Boolean,
default: false,
}),
current: buildProp({
type: Boolean,
default: false,
}),
hiddenExpandIcon: buildProp({
type: Boolean,
default: false,
}),
} as const
export const treeNodeContentProps = {
node: buildProp({
type: definePropType<TreeNode>(Object),
required: true,
} as const),
} as const
// emits
export const NODE_CLICK = 'node-click'
export const NODE_EXPAND = 'node-expand'
export const NODE_COLLAPSE = 'node-collapse'
export const CURRENT_CHANGE = 'current-change'
export const NODE_CHECK = 'check'
export const NODE_CHECK_CHANGE = 'check-change'
export const NODE_CONTEXTMENU = 'node-contextmenu'
export const treeEmits = {
[NODE_CLICK]: (data: TreeNodeData, node: TreeNode) => data && node,
[NODE_EXPAND]: (data: TreeNodeData, node: TreeNode) => data && node,
[NODE_COLLAPSE]: (data: TreeNodeData, node: TreeNode) => data && node,
[CURRENT_CHANGE]: (data: TreeNodeData, node: TreeNode) => data && node,
[NODE_CHECK]: (data: TreeNodeData, checkedInfo: CheckedInfo) =>
data && checkedInfo,
[NODE_CHECK_CHANGE]: (data: TreeNodeData, checked: boolean) =>
data && typeof checked === 'boolean',
[NODE_CONTEXTMENU]: (event: Event, data: TreeNodeData, node: TreeNode) =>
event && data && node,
}
export const treeNodeEmits = {
click: (node: TreeNode) => !!node,
toggle: (node: TreeNode) => !!node,
check: (node: TreeNode, checked: boolean) =>
node && typeof checked === 'boolean',
}