需求背景:需要根据点击后获取的数据动态渲染一个 el-tree,同时渲染出来的 el-tree,需要点击节点时才能获取该节点的层数的获取,如图所示,我需要点击“组”节点才能渲染“设备列表”树,同时“设备列表”树的节点,在我点击具体节点时才能获取具体层数,也就是获取点击节点的数据
源代码:
/** html */
<el-dialog :title="dialog.title" v-model="dialog.visible" width="1200px" append-to-body><el-row :gutter="10"><el-col :span="4"><el-card shadow="hover"><template #header>组:</template><el-tree class="mt-2" ref="deptTreeRef" node-key="id" :current-node-key="groupId":data="instanceGroupTreeOptions" :props="{ label: 'label', children: 'children' }":expand-on-click-node="false" highlight-current default-expand-all@node-click="handleNodeClickWithGroup"><template #default="{ node, data }"><span class="custom-tree-node"><span><el-tooltip :show-after="300" :content="data.label" placement="top-start"><span> {{ ellipsis(data.label, 6) }} </span></el-tooltip></span></span></template></el-tree></el-card></el-col><el-col :span="4"><el-card shadow="hover"><template #header>设备列表:</template><el-tree class="mt-2" ref="deptTreeRef" :load="loadNode":props="{ label: 'name', children: 'children', isLeaf: 'leaf' }" lazy:expand-on-click-node="false" @node-click="handleNodeClickWithInstance"><template #default="{ node, data }"><span class="custom-tree-node"><span><el-tooltip :show-after="300" :content="data.name" placement="top-start"><span> {{ ellipsis(data.name, 6) }} </span></el-tooltip></span></span></template></el-tree></el-card></el-col></el-row></el-dialog>/** js */
import type Node from 'element-plus/es/components/tree/src/model/node'
interface Tree {name: string,leaf?: boolean
}const dialog = reactive<DialogOption>({visible: false,title: '点位选择框'
});
const instanceGroupTreeOptions = ref<InstanceGroupTreeVO[]>([]); //组tree data
const node_had = ref<any>() //存储 loadNode 函数中接受的变量
const resolve_had = ref<any>() //存储 loadNode 函数中接受的变量/** 查询实例组树 */
const getInstanceGroupTree = async () => {const res = await treeInstanceGroup(null);instanceGroupTreeOptions.value = res.data;
};/** 查询设备实例列表 */
const getListInstance = async (query: InstanceQuery) => {const resData = await listInstance(query);instanceList.value = resData.rows;instanceList.value.forEach(item => {item.name = `${item.name}(${item.type})`})console.log(instanceList.value)
};/** 点击 组 树形节点 */
const handleNodeClickWithGroup = async (node: any) => {await getListInstance({projectId: projectId.value,groupId: node.id as string})//点击 组节点后 通过getListInstance 获取 instanceList(第一层设备列表数据) 渲染设备列表树requestNewData()
}/** 动态加载节点数据函数 */
const loadNode = (node: Node, resolve: (data: Tree[]) => void) => {console.log(node)//第一步 当node.level 为0时 先存储函数接收的两个变量//此处的node.level 为0时 表示的是初始化的节点数据 也就是点击了组节点之后展示的第一层设备列表树的数据 也就是根节点 并不显示在树上if (node.level === 0) {//这里将函数接收的两个参数存储起来是将 loadNode手动触发的关键node_had.value = node //此处的node 也可以理解为根节点(看不见)resolve_had.value = resolve //这里的resolve是根节点的 resolvereturn resolve(instanceList.value) //instanceList 就是点击了组节点之后获取的第一层 设备列表的数据}//当需要加载节点数据的node type 为bms时 通过接口获取节点数据/** 这里再说明一下 点击第一层节点后 渲染的数据还是会调用 loadNode 方法 只不过此时不会走 if (node.level === 0) 这个条件 * 此时resolve和node 已经是当前需要加载数据的node 和 resolve*/if (node.data.type == 'bms') {//这段可以修改成你们自己的获取节点数据的接口setTimeout(() => {resolve(instanceList.value)}, 500)} else { //如果不是bms则为空 或者以后增加其他条件resolve([])}
}/** 获取节点数据 */
const requestNewData = () => {node_had.value.childNodes = []; //把存起来的node的子节点清空,不然会界面会出现重复树!这里清空的就是根节点下面的内容loadNode(node_had.value, resolve_had.value); //再次执行懒加载的方法
}onMounted(async () => {await getInstanceGroupTree();
});
关于方法的注释都写在代码片段里面了
大概讲一下,首先 loadNode 方法就是 “设备列表” el-tree 上的一个方法,在页面加载时,会立即调用一次,根据代码中的条件去渲染树,接着,点击 “组” 的树节点,触发“组”树节点点击函数,handleNodeClickWithGroup,根据点击的组节点获取对应的组下的设备列表数据,然后执行 requestNewData 函数 从而实现动态渲染,所以loadNode方法是可以手动触发的
另外再说一点,在loadNode中打印出来的node,当node.level == 0 时,我代码注释中所提到的 “根节点” 是我自己理解的意思 就是由这个 node 渲染出后续的子节点 并且这个 所谓的 “根节点” 并不是显示在页面上(不可见)