<template> <div class="ps-tree component"> <template v-for="(item, index) in list" :key="item.key"> <node @onDragstart="onDragstart" @onDragEnd="onDragEnd" @onDrop="onDrop" :data-source-key="dataSourceKey" :data="item" :list="list" :level="level" @click="(item) => clickNode(item)"> <template #default="{ data, deep, dataSourceKey, status }: { data: INiuTreeData, deep: number, dataSourceKey: INiuTreeKey, status: ENiuTreeStatus }"> <slot :data="data" :deep="deep" :dataSourceKey="dataSourceKey" :status="status"></slot> </template> </node> </template> </div> </template> <script lang="ts" setup> import { INiuTreeData, INiuTreeKey, ENiuTreeStatus } from './type' import { findByKey, forEachTree, insertAfterByKey, insertBeforeByKey, isChildOf, removeByKey, } from './util' const props = withDefaults( defineProps<{ list: INiuTreeData[] justOpen?: boolean autoExpand?: boolean justOpenOne?: boolean level?: number }>(), { justOpenOne: false, justOpen: false, autoExpand: false, level: 0, } ) provide("tree:opts", props) function clickNode(item: INiuTreeData) { if (props.justOpenOne) { forEachTree(props.list, (node: INiuTreeData) => { node.isExpand = false }) } if (item.isFolder) { item.isExpand = !item.isExpand emit("change") } } const emit = defineEmits<{ (e: 'change'): void }>() const dataSourceKey = ref() function onDragstart(key: INiuTreeKey) { dataSourceKey.value = key } function onDragEnd(key: INiuTreeKey) { dataSourceKey.value = undefined } function onDrop(key: INiuTreeKey, status?: ENiuTreeStatus) { if (!dataSourceKey.value) return if (!key) return let data = findByKey(dataSourceKey.value, props.list) let targetData = findByKey(key, props.list) switch (status) { case ENiuTreeStatus.DragIn: if ( data && targetData && dataSourceKey.value != key && !isChildOf(key, dataSourceKey.value, props.list) && targetData.children ) { removeByKey(dataSourceKey.value, props.list) targetData.children.push(data) if (props.autoExpand) { targetData.isExpand = true } emit("change") } break case ENiuTreeStatus.DragDown: // 按索引往列表添加节点 if ( data && targetData && dataSourceKey.value != key && !isChildOf(key, dataSourceKey.value, props.list) ) { removeByKey(dataSourceKey.value, props.list) insertAfterByKey(key, data, props.list) emit("change") } break case ENiuTreeStatus.DragUp: // 按索引往列表添加节点 if ( data && targetData && dataSourceKey.value != key && !isChildOf(key, dataSourceKey.value, props.list) ) { removeByKey(dataSourceKey.value, props.list) insertBeforeByKey(key, data, props.list) emit("change") } break } dataSourceKey.value = undefined } </script> <script lang="ts"> import { defineComponent, provide, ref } from "vue" import node from './node.vue' export default defineComponent({ name: 'ps-tree', }) </script>