使用el-tree的懒加载特性实现,核心在于对load的实现。
el-tree加载后,会自动调用load关联函数,加载一级数据。在load函数中进行判断,0级加载第一级和第二级数据,然后展开子节点并加载数据。这样组件加载后展示效果更好。
<template>
<el-tree lazy node-key="id" :load="loadData" :props="roomProps" />
</template>
<script setup lang="ts">
defineOptions({ name: 'RoomSelect' })
import { ProjectInfoApi } from '@/api/village/projectinfo'
import { FloorInfoApi } from '@/api/village/floorinfo'
import { RoomInfoApi } from '@/api/village/roominfo'
const projectAndBuildings = ref<any[]>([]) // 楼宇列表
const projectAndBuildingsMap = ref<{}>({}) // 楼宇列表 Map
/** 树形结构配置 */
const roomProps = ref({
label: 'name',
value: 'id',
children: 'data',
isLeaf: 'leaf'
})
/** 节点构造 */
const loadData = async (node, resolve) => {
if (node.level === 0) {
await loadProjectAndBuildings()
resolve(projectAndBuildings.value)
// 解析后展开第一级节点
node.childNodes.forEach((childNode) => {
childNode.expanded = true
childNode.loadData()
})
} else if (node.level === 1) {
resolve(projectAndBuildingsMap.value[node.data.id].data)
} else if (node.level === 2) {
resolve(await loadFloor(node.data.id))
} else if (node.level === 3) {
resolve(await loadRoom(node.data.id))
}
}
/** 加载项目和楼栋 */
const loadProjectAndBuildings = async () => {
projectAndBuildings.value = addIsLeafFlag(await ProjectInfoApi.getProjectAndBuildingList())
projectAndBuildingsMap.value = projectAndBuildings.value.reduce((acc, item) => {
acc[item.id] = item // 使用 item.id 作为键,将 item 作为值
return acc
}, {})
}
/** 项目和楼栋数据转换 */
function addIsLeafFlag(datas) {
datas.forEach((data) => {
data.leaf = data.data?.length === 0 // 如果当前节点没有子节点,则添加 isLeaf 属性
data.data?.forEach((building) => {
building.leaf = false // 给每个建筑添加 isLeaf 属性
building.data = []
})
})
return datas
}
/** 加载楼层 */
const loadFloor = async (buildingId) => {
const datas = await FloorInfoApi.getFloorInfoSimpleList(buildingId)
datas.forEach((item) => {
item.name = item.floorName
})
return datas
}
/** 加载房间 */
const loadRoom = async (floorId) => {
const datas = await RoomInfoApi.getRoomInfoSimpleList(floorId)
datas.forEach((item) => {
item.name = item.roomName
item.leaf = true
})
return datas
}
</script>