问题描述
思路:先 getSysPermissionListApi()
通过API获取权限树的模型,然后在通过 getSysRolePermissionApi()
选中当前用户的权限。
问题:打开权限树时,树出来了,但是用户的权限没有被选中
<template>
<div>
<p>{{ roleId }}</p>
<el-tree
ref="permTreeRef"
style="max-width: 600px"
:data="transformPermissionsToTree(permissionsBaseData)"
node-key="id"
show-checkbox
default-expand-all
v-loading="permissionsTreeLoading"
/>
</div>
</template>
const initPermissionTree = async () => {
try {
permissionsTreeLoading.value = true
const permList = await getSysPermissionListApi({
pageNum: 1,
pageSize: 9999
})
permissionsBaseData.value = permList.data
if (roleId.value) {
const rolePerms = await getSysRolePermissionApi(roleId.value)
permissionsUserData.value = rolePerms.data.map((item) => item.permissionId)
rolePerms.data.forEach((item) => permTreeRef.value?.setChecked(item.permissionId, true, false))
}
} catch (err) {
console.error("Failed to init permission tree:", err)
} finally {
permissionsTreeLoading.value = false
}
}
// // 监听 roleId 变化
watch(() => roleId.value, initPermissionTree, { immediate: true })
问题分析
问题出在 DOM
<el-tree
...
:data="transformPermissionsToTree(permissionsBaseData)"
...
/>
首先 permissionsBaseData
数据需要经过 transformPermissionsToTree(permissionsBaseData)
给到 el-tree
树,那么el-tree才可以显示数据。
但是我获取完数据直接就是 permTreeRef.value?.setChecked
设置选中项,但是这个时候DOM还没更新,那么 el-tree
就无法从 transformPermissionsToTree(permissionsBaseData)
获取数据。
DOM
树中还没刷新,也就意味着当前 permTreeRef.value
是空的,那无法选中也合理了。
解决办法
第一种 计算属性
设置个计算属性,这样 Tree
就不再依赖 DOM 更新了,通过计算属性实时更新。
const treeData = computed<Tree[]>(() => {
return transformPermissionsToTree(permissionsBaseData.value)
})
<el-tree
ref="permTreeRef"
style="max-width: 600px"
:data="treeData"
node-key="id"
show-checkbox
default-expand-all
v-loading="permissionsTreeLoading"
/>
第二种 nextTick
使用 nextTick 等待 DOM 更新完成后,再运行。
nextTick(async () => {
if (roleId.value) {
const rolePerms = await getSysRolePermissionApi(roleId.value)
permissionsUserData.value = rolePerms.data.map((item) => item.permissionId)
rolePerms.data.forEach((item) => permTreeRef.value?.setChecked(item.permissionId, true, false))
}
})