refactor(components): [tree] remove ts-nocheck (#21097)

* chore: wip

* chore: wip

* chore: wip

* chore: wip

* chore: fix

* chore: fix

* chore: cleanup

* chore: fix

* fix: review

Co-authored-by: btea <2356281422@qq.com>

---------

Co-authored-by: btea <2356281422@qq.com>
This commit is contained in:
Noblet Ouways
2025-06-24 09:01:53 +02:00
committed by GitHub
parent 327922d4b2
commit c57b0cab42
10 changed files with 204 additions and 138 deletions

View File

@@ -68,7 +68,7 @@ const append = (data: Data) => {
const remove = (node: Node, data: Data) => {
const parent = node.parent
const children: Tree[] = parent.data.children || parent.data
const children: Tree[] = parent?.data.children || parent?.data
const index = children.findIndex((d) => d.id === data.id)
children.splice(index, 1)
dataSource.value = [...dataSource.value]

View File

@@ -5,11 +5,6 @@
<script lang="ts" setup>
import type { LoadFunction } from 'element-plus'
interface Tree {
name: string
leaf?: boolean
}
const props = {
label: 'name',
children: 'zones',

View File

@@ -1,5 +1,5 @@
// @ts-nocheck
import { reactive } from 'vue'
import { isNil } from 'lodash-unified'
import {
hasOwn,
isArray,
@@ -67,7 +67,7 @@ const reInitChecked = function (node: Node): void {
const getPropertyFromData = function (node: Node, prop: string): any {
const props = node.store.props
const data = node.data || {}
const config = props[prop]
const config = (props as any)[prop]
if (isFunction(config)) {
return config(data, node)
@@ -83,17 +83,17 @@ let nodeIdSeed = 0
class Node {
id: number
text: string
text: string | null
checked: boolean
indeterminate: boolean
data: TreeNodeData
expanded: boolean
parent: Node
parent: Node | null
visible: boolean
isCurrent: boolean
store: TreeStore
isLeafByUser: boolean
isLeaf: boolean
store!: TreeStore
isLeafByUser: boolean | undefined = undefined
isLeaf: boolean | undefined = undefined
canFocus: boolean
level: number
@@ -106,9 +106,9 @@ class Node {
this.text = null
this.checked = false
this.indeterminate = false
this.data = null
this.data = null as unknown as TreeNodeData
this.expanded = false
this.parent = null
this.parent = null as Node | null
this.visible = true
this.isCurrent = false
this.canFocus = false
@@ -168,7 +168,12 @@ class Node {
const defaultExpandedKeys = store.defaultExpandedKeys
const key = store.key
if (key && defaultExpandedKeys && defaultExpandedKeys.includes(this.key)) {
if (
key &&
!isNil(this.key) &&
defaultExpandedKeys &&
defaultExpandedKeys.includes(this.key)
) {
this.expand(null, store.autoExpandParent)
}
@@ -186,8 +191,7 @@ class Node {
}
this.updateLeafState()
if (this.parent && (this.level === 1 || this.parent.expanded === true))
this.canFocus = true
if (this.level === 1 || this.parent?.expanded === true) this.canFocus = true
}
setData(data: TreeNodeData): void {
@@ -214,7 +218,7 @@ class Node {
return getPropertyFromData(this, 'label')
}
get key(): TreeKey {
get key(): TreeKey | null | undefined {
const nodeKey = this.store.key
if (this.data) return this.data[nodeKey]
return null
@@ -265,11 +269,11 @@ class Node {
if (!(child instanceof Node)) {
if (!batch) {
const children = this.getChildren(true)
if (!children.includes(child.data)) {
if (!children?.includes(child.data)) {
if (isUndefined(index) || index < 0) {
children.push(child.data)
children?.push(child.data)
} else {
children.splice(index, 0, child.data)
children?.splice(index, 0, child.data)
}
}
}
@@ -329,8 +333,8 @@ class Node {
this.updateLeafState()
}
removeChildByData(data: TreeNodeData): void {
let targetNode: Node = null
removeChildByData(data: TreeNodeData | null): void {
let targetNode: Node | null = null
for (let i = 0; i < this.childNodes.length; i++) {
if (this.childNodes[i].data === data) {
@@ -344,11 +348,11 @@ class Node {
}
}
expand(callback?: () => void, expandParent?: boolean): void {
const done = (): void => {
expand(callback?: (() => void) | null, expandParent?: boolean): void {
const done = () => {
if (expandParent) {
let parent = this.parent
while (parent.level > 0) {
while (parent && parent.level > 0) {
parent.expanded = true
parent = parent.parent
}
@@ -396,8 +400,8 @@ class Node {
})
}
shouldLoadData(): boolean {
return this.store.lazy === true && this.store.load && !this.loaded
shouldLoadData() {
return Boolean(this.store.lazy === true && this.store.load && !this.loaded)
}
updateLeafState(): void {
@@ -481,7 +485,7 @@ class Node {
}
}
getChildren(forceInit = false): TreeNodeData | TreeNodeData[] {
getChildren(forceInit = false): TreeNodeData | TreeNodeData[] | null {
// this is data
if (this.level === 0) return this.data
const data = this.data
@@ -508,13 +512,13 @@ class Node {
const newData = (this.getChildren() || []) as TreeNodeData[]
const oldData = this.childNodes.map((node) => node.data)
const newDataMap = {}
const newNodes = []
const newDataMap: Record<TreeKey, TreeNodeData> = {}
const newNodes: TreeNodeData[] = []
newData.forEach((item, index) => {
const key = item[NODE_KEY]
const isNodeExists =
!!key && oldData.findIndex((data) => data[NODE_KEY] === key) >= 0
!!key && oldData.findIndex((data) => data?.[NODE_KEY] === key) >= 0
if (isNodeExists) {
newDataMap[key] = { index, data: item }
} else {
@@ -524,7 +528,7 @@ class Node {
if (!this.store.lazy) {
oldData.forEach((item) => {
if (!newDataMap[item[NODE_KEY]]) this.removeChildByData(item)
if (!newDataMap[item?.[NODE_KEY]]) this.removeChildByData(item)
})
}
@@ -536,7 +540,7 @@ class Node {
}
loadData(
callback: (node: Node) => void,
callback: (data?: TreeNodeData[]) => void,
defaultProps: TreeNodeLoadedDefaultProps = {}
) {
if (
@@ -547,7 +551,7 @@ class Node {
) {
this.loading = true
const resolve = (children) => {
const resolve = (children: TreeNodeData[]) => {
this.childNodes = []
this.doCreateChildren(children, defaultProps)

View File

@@ -1,6 +1,6 @@
// @ts-nocheck
import { nextTick } from 'vue'
import { hasOwn, isObject, isPropAbsent } from '@element-plus/utils'
import { isNil } from 'lodash-unified'
import { NOOP, hasOwn, isObject, isPropAbsent } from '@element-plus/utils'
import Node from './node'
import { getNodeKey } from './util'
@@ -17,22 +17,22 @@ import type {
} from '../tree.type'
export default class TreeStore {
currentNode: Node
currentNodeKey: TreeKey
currentNode: Node | null
currentNodeKey: TreeKey | null
nodesMap: TreeStoreNodesMap
root: Node
data: TreeData
lazy: boolean
load: LoadFunction
filterNodeMethod: FilterNodeMethodFunction
key: TreeKey
defaultCheckedKeys: TreeKey[]
checkStrictly: boolean
defaultExpandedKeys: TreeKey[]
autoExpandParent: boolean
defaultExpandAll: boolean
checkDescendants: boolean
props: TreeOptionProps
root!: Node
data!: TreeData
lazy = false
load?: LoadFunction
filterNodeMethod?: FilterNodeMethodFunction
key!: TreeKey
defaultCheckedKeys?: TreeKey[]
checkStrictly = false
defaultExpandedKeys?: TreeKey[]
autoExpandParent = false
defaultExpandAll = false
checkDescendants = false
props!: TreeOptionProps
constructor(options: TreeStoreOptions) {
this.currentNode = null
@@ -56,10 +56,14 @@ export default class TreeStore {
if (this.lazy && this.load) {
const loadFn = this.load
loadFn(this.root, (data) => {
this.root.doCreateChildren(data)
this._initDefaultCheckedNodes()
})
loadFn(
this.root,
(data) => {
this.root.doCreateChildren(data)
this._initDefaultCheckedNodes()
},
NOOP
)
} else {
this._initDefaultCheckedNodes()
}
@@ -74,7 +78,12 @@ export default class TreeStore {
: (node as Node).childNodes
for (const [index, child] of childNodes.entries()) {
child.visible = filterNodeMethod.call(child, value, child.data, child)
child.visible = !!filterNodeMethod?.call(
child,
value,
child.data,
child
)
if (index % 80 === 0 && index > 0) {
await nextTick()
@@ -95,7 +104,7 @@ export default class TreeStore {
if (!value) return
if ((node as Node).visible && !(node as Node).isLeaf) {
if (!lazy || node.loaded) {
if (!lazy || (node as Node).loaded) {
;(node as Node).expand()
}
}
@@ -127,7 +136,7 @@ export default class TreeStore {
refData: TreeKey | TreeNodeData | Node
): void {
const refNode = this.getNode(refData)
refNode.parent.insertBefore({ data }, refNode)
refNode.parent?.insertBefore({ data }, refNode)
}
insertAfter(
@@ -135,7 +144,7 @@ export default class TreeStore {
refData: TreeKey | TreeNodeData | Node
): void {
const refNode = this.getNode(refData)
refNode.parent.insertAfter({ data }, refNode)
refNode.parent?.insertAfter({ data }, refNode)
}
remove(data: TreeNodeData | Node): void {
@@ -175,7 +184,7 @@ export default class TreeStore {
_initDefaultCheckedNode(node: Node): void {
const defaultCheckedKeys = this.defaultCheckedKeys || []
if (defaultCheckedKeys.includes(node.key)) {
if (!isNil(node.key) && defaultCheckedKeys.includes(node.key)) {
node.setChecked(true, !this.checkStrictly)
}
}
@@ -195,7 +204,7 @@ export default class TreeStore {
this.nodesMap[node.id] = node
} else {
const nodeKey = node.key
if (nodeKey !== undefined) this.nodesMap[node.key] = node
if (!isNil(nodeKey)) this.nodesMap[nodeKey] = node
}
}
@@ -207,7 +216,7 @@ export default class TreeStore {
this.deregisterNode(child)
})
delete this.nodesMap[node.key]
delete this.nodesMap[node.key!]
}
getCheckedNodes(
@@ -296,12 +305,12 @@ export default class TreeStore {
key: TreeKey,
leafOnly = false,
checkedKeys: { [key: string]: boolean }
): void {
) {
const allNodes = this._getAllNodes().sort((a, b) => a.level - b.level)
const cache = Object.create(null)
const cache: Record<TreeKey, boolean> = Object.create(null)
const keys = Object.keys(checkedKeys)
allNodes.forEach((node) => node.setChecked(false, false))
const cacheCheckedChild = (node) => {
const cacheCheckedChild = (node: Node) => {
node.childNodes.forEach((child) => {
cache[child.data[key]] = true
if (child.childNodes?.length) {
@@ -311,7 +320,7 @@ export default class TreeStore {
}
for (let i = 0, j = allNodes.length; i < j; i++) {
const node = allNodes[i]
const nodeKey = node.data[key].toString()
const nodeKey: string = node.data[key].toString()
const checked = keys.includes(nodeKey)
if (!checked) {
if (node.checked && !cache[nodeKey]) {
@@ -348,9 +357,9 @@ export default class TreeStore {
setCheckedNodes(array: Node[], leafOnly = false): void {
const key = this.key
const checkedKeys = {}
const checkedKeys: Record<TreeKey, boolean> = {}
array.forEach((item) => {
checkedKeys[(item || {})[key]] = true
checkedKeys[((item || {}) as any)[key]] = true
})
this._setCheckedKeys(key, leafOnly, checkedKeys)
@@ -359,7 +368,7 @@ export default class TreeStore {
setCheckedKeys(keys: TreeKey[], leafOnly = false): void {
this.defaultCheckedKeys = keys
const key = this.key
const checkedKeys = {}
const checkedKeys: Record<TreeKey, boolean> = {}
keys.forEach((key) => {
checkedKeys[key] = true
})
@@ -388,7 +397,7 @@ export default class TreeStore {
}
}
getCurrentNode(): Node {
getCurrentNode() {
return this.currentNode
}
@@ -402,15 +411,19 @@ export default class TreeStore {
}
setUserCurrentNode(node: Node, shouldAutoExpandParent = true): void {
const key = node[this.key]
const key = (node as any)[this.key]
const currNode = this.nodesMap[key]
this.setCurrentNode(currNode)
if (shouldAutoExpandParent && this.currentNode.level > 1) {
this.currentNode.parent.expand(null, true)
if (
shouldAutoExpandParent &&
this.currentNode &&
this.currentNode.level > 1
) {
this.currentNode.parent?.expand(null, true)
}
}
setCurrentNodeKey(key?: TreeKey, shouldAutoExpandParent = true): void {
setCurrentNodeKey(key: TreeKey | null, shouldAutoExpandParent = true): void {
this.currentNodeKey = key
if (isPropAbsent(key)) {
this.currentNode && (this.currentNode.isCurrent = false)
@@ -420,8 +433,12 @@ export default class TreeStore {
const node = this.getNode(key)
if (node) {
this.setCurrentNode(node)
if (shouldAutoExpandParent && this.currentNode.level > 1) {
this.currentNode.parent.expand(null, true)
if (
shouldAutoExpandParent &&
this.currentNode &&
this.currentNode.level > 1
) {
this.currentNode.parent?.expand(null, true)
}
}
}

View File

@@ -1,11 +1,16 @@
// @ts-nocheck
import { provide, ref } from 'vue'
import { addClass, isFunction, removeClass } from '@element-plus/utils'
import { useNamespace } from '@element-plus/hooks'
import type { InjectionKey } from 'vue'
import type { InjectionKey, Ref, SetupContext } from 'vue'
import type {
AllowDragFunction,
AllowDropFunction,
FakeNode,
NodeDropType,
} from '../tree.type'
import type TreeStore from './tree-store'
import type Node from './node'
import type { NodeDropType } from '../tree.type'
interface TreeNode {
node: Node
@@ -17,6 +22,17 @@ interface DragOptions {
treeNode: TreeNode
}
interface Props {
props: {
allowDrag?: AllowDragFunction
allowDrop?: AllowDropFunction
}
ctx: SetupContext<string[]>
el$: Ref<HTMLElement | null>
dropIndicator$: Ref<HTMLElement | null>
store: Ref<TreeStore>
}
export interface DragEvents {
treeNodeDragStart: (options: DragOptions) => void
treeNodeDragOver: (options: DragOptions) => void
@@ -25,9 +41,21 @@ export interface DragEvents {
export const dragEventsKey: InjectionKey<DragEvents> = Symbol('dragEvents')
export function useDragNodeHandler({ props, ctx, el$, dropIndicator$, store }) {
export function useDragNodeHandler({
props,
ctx,
el$,
dropIndicator$,
store,
}: Props) {
const ns = useNamespace('tree')
const dragState = ref({
const dragState = ref<{
allowDrop: boolean
dropType: NodeDropType | null
draggingNode: TreeNode | null
showDropIndicator: boolean
dropNode: TreeNode | null
}>({
showDropIndicator: false,
draggingNode: null,
dropNode: null,
@@ -36,6 +64,7 @@ export function useDragNodeHandler({ props, ctx, el$, dropIndicator$, store }) {
})
const treeNodeDragStart = ({ event, treeNode }: DragOptions) => {
if (!event.dataTransfer) return
if (isFunction(props.allowDrag) && !props.allowDrag(treeNode.node)) {
event.preventDefault()
return false
@@ -53,10 +82,11 @@ export function useDragNodeHandler({ props, ctx, el$, dropIndicator$, store }) {
}
const treeNodeDragOver = ({ event, treeNode }: DragOptions) => {
if (!event.dataTransfer) return
const dropNode = treeNode
const oldDropNode = dragState.value.dropNode
if (oldDropNode && oldDropNode.node.id !== dropNode.node.id) {
removeClass(oldDropNode.$el, ns.is('drop-inner'))
removeClass(oldDropNode.$el!, ns.is('drop-inner'))
}
const draggingNode = dragState.value.draggingNode
if (!draggingNode || !dropNode) return
@@ -110,12 +140,13 @@ export function useDragNodeHandler({ props, ctx, el$, dropIndicator$, store }) {
dropInner = false
dropNext = false
}
const dropEl = dropNode.$el!
// find target node without children, just calc content node height
const targetPosition = dropNode.$el
.querySelector(`.${ns.be('node', 'content')}`)
const targetPosition = dropEl
.querySelector(`.${ns.be('node', 'content')}`)!
.getBoundingClientRect()
const treePosition = el$.value.getBoundingClientRect()
const treePosition = el$.value!.getBoundingClientRect()
let dropType: NodeDropType
const prevPercent = dropPrev ? (dropInner ? 0.25 : dropNext ? 0.45 : 1) : -1
@@ -133,8 +164,8 @@ export function useDragNodeHandler({ props, ctx, el$, dropIndicator$, store }) {
dropType = 'none'
}
const iconPosition = dropNode.$el
.querySelector(`.${ns.be('node', 'expand-icon')}`)
const iconPosition = dropEl
.querySelector(`.${ns.be('node', 'expand-icon')}`)!
.getBoundingClientRect()
const dropIndicator = dropIndicator$.value
if (dropType === 'before') {
@@ -142,13 +173,13 @@ export function useDragNodeHandler({ props, ctx, el$, dropIndicator$, store }) {
} else if (dropType === 'after') {
indicatorTop = iconPosition.bottom - treePosition.top
}
dropIndicator.style.top = `${indicatorTop}px`
dropIndicator.style.left = `${iconPosition.right - treePosition.left}px`
dropIndicator!.style.top = `${indicatorTop}px`
dropIndicator!.style.left = `${iconPosition.right - treePosition.left}px`
if (dropType === 'inner') {
addClass(dropNode.$el, ns.is('drop-inner'))
addClass(dropEl, ns.is('drop-inner'))
} else {
removeClass(dropNode.$el, ns.is('drop-inner'))
removeClass(dropEl, ns.is('drop-inner'))
}
dragState.value.showDropIndicator =
@@ -168,20 +199,20 @@ export function useDragNodeHandler({ props, ctx, el$, dropIndicator$, store }) {
event.dataTransfer.dropEffect = 'move'
}
if (draggingNode && dropNode) {
const draggingNodeCopy = { data: draggingNode.node.data }
if (draggingNode?.node.data && dropNode) {
const draggingNodeCopy: FakeNode = { data: draggingNode.node.data }
if (dropType !== 'none') {
draggingNode.node.remove()
}
if (dropType === 'before') {
dropNode.node.parent.insertBefore(draggingNodeCopy, dropNode.node)
dropNode.node.parent?.insertBefore(draggingNodeCopy, dropNode.node)
} else if (dropType === 'after') {
dropNode.node.parent.insertAfter(draggingNodeCopy, dropNode.node)
dropNode.node.parent?.insertAfter(draggingNodeCopy, dropNode.node)
} else if (dropType === 'inner') {
dropNode.node.insertChild(draggingNodeCopy)
}
if (dropType !== 'none') {
store.value.registerNode(draggingNodeCopy)
store.value.registerNode(draggingNodeCopy as any)
if (store.value.key) {
//restore checkbox state after dragging
draggingNode.node.eachNode((node) => {
@@ -193,7 +224,7 @@ export function useDragNodeHandler({ props, ctx, el$, dropIndicator$, store }) {
}
}
removeClass(dropNode.$el, ns.is('drop-inner'))
removeClass(dropNode.$el!, ns.is('drop-inner'))
ctx.emit(
'node-drag-end',

View File

@@ -1,4 +1,3 @@
// @ts-nocheck
import { onMounted, onUpdated } from 'vue'
import { useEventListener } from '@vueuse/core'
import { EVENT_CODE } from '@element-plus/constants'
@@ -9,7 +8,7 @@ import type { Ref } from 'vue'
import type { Nullable } from '@element-plus/utils'
interface UseKeydownOption {
el$: Ref<HTMLElement>
el$: Ref<HTMLElement | null>
}
export function useKeydown({ el$ }: UseKeydownOption, store: Ref<TreeStore>) {
const ns = useNamespace('tree')
@@ -20,7 +19,7 @@ export function useKeydown({ el$ }: UseKeydownOption, store: Ref<TreeStore>) {
onUpdated(() => {
const checkboxItems = Array.from(
el$.value.querySelectorAll('input[type=checkbox]')
el$.value!.querySelectorAll('input[type=checkbox]')
)
checkboxItems.forEach((checkbox) => {
checkbox.setAttribute('tabindex', '-1')
@@ -28,11 +27,11 @@ export function useKeydown({ el$ }: UseKeydownOption, store: Ref<TreeStore>) {
})
const handleKeydown = (ev: KeyboardEvent): void => {
const currentItem = ev.target as HTMLElement
const currentItem = ev.target as HTMLDivElement
if (!currentItem.className.includes(ns.b('node'))) return
const code = ev.code
const treeItems = Array.from(
el$.value.querySelectorAll(`.${ns.is('focusable')}[role=treeitem]`)
const treeItems: HTMLElement[] = Array.from(
el$.value!.querySelectorAll(`.${ns.is('focusable')}[role=treeitem]`)
)
const currentIndex = treeItems.indexOf(currentItem)
let nextIndex
@@ -47,7 +46,7 @@ export function useKeydown({ el$ }: UseKeydownOption, store: Ref<TreeStore>) {
: treeItems.length - 1
const startIndex = nextIndex
while (true) {
if (store.value.getNode(treeItems[nextIndex].dataset.key).canFocus)
if (store.value.getNode(treeItems[nextIndex].dataset.key!).canFocus)
break
nextIndex--
if (nextIndex === startIndex) {
@@ -67,7 +66,7 @@ export function useKeydown({ el$ }: UseKeydownOption, store: Ref<TreeStore>) {
: 0
const startIndex = nextIndex
while (true) {
if (store.value.getNode(treeItems[nextIndex].dataset.key).canFocus)
if (store.value.getNode(treeItems[nextIndex].dataset.key!).canFocus)
break
nextIndex++
if (nextIndex === startIndex) {
@@ -102,6 +101,7 @@ export function useKeydown({ el$ }: UseKeydownOption, store: Ref<TreeStore>) {
useEventListener(el$, 'keydown', handleKeydown)
const initTabIndex = (): void => {
if (!el$.value) return
const treeItems = Array.from(
el$.value.querySelectorAll(`.${ns.is('focusable')}[role=treeitem]`)
)

View File

@@ -1,20 +1,27 @@
// @ts-nocheck
import { inject, provide } from 'vue'
import { TREE_NODE_MAP_INJECTION_KEY } from '../tokens'
import type Node from '../model/node'
interface NodeMap {
treeNodeExpand(node: Node): void
treeNodeExpand(node?: Node): void
children: NodeMap[]
}
export function useNodeExpandEventBroadcast(props) {
const parentNodeMap = inject<NodeMap>(TREE_NODE_MAP_INJECTION_KEY, null)
interface Props {
node?: Node
accordion: boolean
}
export function useNodeExpandEventBroadcast(props: Props) {
const parentNodeMap = inject(
TREE_NODE_MAP_INJECTION_KEY,
null
) as NodeMap | null
const currentNodeMap: NodeMap = {
treeNodeExpand: (node) => {
if (props.node !== node) {
props.node.collapse()
props.node?.collapse()
}
},
children: [],
@@ -27,7 +34,7 @@ export function useNodeExpandEventBroadcast(props) {
provide(TREE_NODE_MAP_INJECTION_KEY, currentNodeMap)
return {
broadcastExpanded: (node: Node): void => {
broadcastExpanded: (node?: Node): void => {
if (!props.accordion) return
for (const childNode of currentNodeMap.children) {
childNode.treeNodeExpand(node)

View File

@@ -4,7 +4,10 @@ import type { RootTreeType, TreeKey, TreeNodeData } from '../tree.type'
export const NODE_KEY = '$treeNodeId'
export const markNodeData = function (node: Node, data: TreeNodeData): void {
export const markNodeData = function (
node: Node,
data: TreeNodeData | null
): void {
if (!data || data[NODE_KEY]) return
Object.defineProperty(data, NODE_KEY, {
value: node.id,
@@ -14,7 +17,7 @@ export const markNodeData = function (node: Node, data: TreeNodeData): void {
})
}
export const getNodeKey = (key: TreeKey, data: TreeNodeData) =>
export const getNodeKey = (key: TreeKey | undefined, data: TreeNodeData) =>
data?.[key || NODE_KEY]
export const handleCurrentChange = (

View File

@@ -43,19 +43,19 @@ export interface TreeStoreNodesMap {
[key: string]: Node
}
export interface TreeStoreOptions {
key: TreeKey
key?: TreeKey
data: TreeData
lazy: boolean
props: TreeOptionProps
load: LoadFunction
currentNodeKey: TreeKey
load?: LoadFunction
currentNodeKey?: TreeKey
checkStrictly: boolean
checkDescendants: boolean
defaultCheckedKeys: TreeKey[]
defaultExpandedKeys: TreeKey[]
defaultCheckedKeys?: TreeKey[]
defaultExpandedKeys?: TreeKey[]
autoExpandParent: boolean
defaultExpandAll: boolean
filterNodeMethod: FilterNodeMethodFunction
filterNodeMethod?: FilterNodeMethodFunction
}
export interface TreeOptionProps {
children?: string

View File

@@ -37,7 +37,6 @@
</template>
<script lang="ts">
// @ts-nocheck
import {
computed,
defineComponent,
@@ -47,7 +46,7 @@ import {
ref,
watch,
} from 'vue'
import { iconPropType } from '@element-plus/utils'
import { definePropType, iconPropType } from '@element-plus/utils'
import { useLocale, useNamespace } from '@element-plus/hooks'
import { formItemContextKey } from '@element-plus/components/form'
import { selectKey } from '@element-plus/components/select/src/token'
@@ -63,6 +62,10 @@ import type Node from './model/node'
import type { ComponentInternalInstance, PropType } from 'vue'
import type { Nullable } from '@element-plus/utils'
import type {
AllowDragFunction,
AllowDropFunction,
FilterValue,
RenderContentFunction,
TreeComponentProps,
TreeData,
TreeKey,
@@ -74,7 +77,7 @@ export default defineComponent({
components: { ElTreeNode },
props: {
data: {
type: Array,
type: definePropType<TreeData>(Array),
default: () => [],
},
emptyText: {
@@ -111,7 +114,9 @@ export default defineComponent({
TreeComponentProps['defaultExpandedKeys']
>,
currentNodeKey: [String, Number] as PropType<string | number>,
renderContent: Function,
renderContent: {
type: definePropType<RenderContentFunction>(Function),
},
showCheckbox: {
type: Boolean,
default: false,
@@ -120,8 +125,12 @@ export default defineComponent({
type: Boolean,
default: false,
},
allowDrag: Function,
allowDrop: Function,
allowDrag: {
type: definePropType<AllowDragFunction>(Function),
},
allowDrop: {
type: definePropType<AllowDropFunction>(Function),
},
props: {
type: Object as PropType<TreeComponentProps['props']>,
default: () => ({
@@ -162,7 +171,7 @@ export default defineComponent({
'node-drag-leave',
'node-drag-enter',
'node-drag-over',
],
] as string[],
setup(props, ctx) {
const { t } = useLocale()
const ns = useNamespace('tree')
@@ -189,7 +198,7 @@ export default defineComponent({
store.value.initialize()
const root = ref<Node>(store.value.root)
const currentNode = ref<Node>(null)
const currentNode = ref<Node | null>(null)
const el$ = ref<Nullable<HTMLElement>>(null)
const dropIndicator$ = ref<Nullable<HTMLElement>>(null)
@@ -208,7 +217,7 @@ export default defineComponent({
const isEmpty = computed(() => {
const { childNodes } = root.value
const hasFilteredOptions = selectInfo
? selectInfo.hasFilteredOptions !== 0
? (selectInfo as any).hasFilteredOptions !== 0
: false
return (
(!childNodes ||
@@ -221,21 +230,21 @@ export default defineComponent({
watch(
() => props.currentNodeKey,
(newVal) => {
store.value.setCurrentNodeKey(newVal)
store.value.setCurrentNodeKey(newVal ?? null)
}
)
watch(
() => props.defaultCheckedKeys,
(newVal) => {
store.value.setDefaultCheckedKey(newVal)
store.value.setDefaultCheckedKey(newVal ?? [])
}
)
watch(
() => props.defaultExpandedKeys,
(newVal) => {
store.value.setDefaultExpandedKeys(newVal)
store.value.setDefaultExpandedKeys(newVal ?? [])
}
)
@@ -254,7 +263,7 @@ export default defineComponent({
}
)
const filter = (value) => {
const filter = (value: FilterValue) => {
if (!props.filterNodeMethod)
throw new Error('[Tree] filterNodeMethod is required when filter')
store.value.filter(value)
@@ -289,12 +298,12 @@ export default defineComponent({
return store.value.getCheckedKeys(leafOnly)
}
const getCurrentNode = (): TreeNodeData => {
const getCurrentNode = () => {
const currentNode = store.value.getCurrentNode()
return currentNode ? currentNode.data : null
}
const getCurrentKey = (): any => {
const getCurrentKey = (): TreeKey | null => {
if (!props.nodeKey)
throw new Error('[Tree] nodeKey is required in getCurrentKey')
const currentNode = getCurrentNode()
@@ -345,7 +354,7 @@ export default defineComponent({
handleCurrentChange(store, ctx.emit, () => {
broadcastExpanded()
store.value.setCurrentNodeKey(key, shouldAutoExpandParent)
store.value.setCurrentNodeKey(key ?? null, shouldAutoExpandParent)
})
}
@@ -400,7 +409,7 @@ export default defineComponent({
root,
currentNode,
instance: getCurrentInstance(),
} as any)
})
provide(formItemContextKey, undefined)