
在现代 Web 应用开发中,菜单权限配置是一个至关重要的功能,它确保不同角色的用户能够访问特定的功能模块。Vue 3 作为一款流行的 JavaScript 框架,为我们提供了高效且灵活的方式来构建这样的界面。本文将通过实际代码示例,详细讲解如何在 Vue 3 中搭建一个菜单权限配置界面。

一、界面基础结构搭建
我们使用 Element Plus 库来构建用户界面。在<template>部分,我们创建了一个el-dialog组件,作为菜单权限配置的弹窗。
html
<el-dialog
title="菜单权限"
width="1000"
center
destroy-on-close
@open="dialogOpen"
>
<div>
<div>角色名称:jiaberr</div>
<div>
<text>菜单权限:</text>
<el-checkbox v-model="expandAll" @change="handleExpandAllChange">
展开/折叠
</el-checkbox>
<el-checkbox v-model="checkAll" @change="handleCheckAllChange">
全选/全不选
</el-checkbox>
<el-checkbox v-model="checkStrictly"> 父子联动 </el-checkbox>
</div>
<div class="w-p-100 containner">
<el-tree
ref="treeRef"
:props="treeProps"
:data="menudatas"
show-checkbox
node-key="id"
:check-strictly="!checkStrictly"
:default-expanded-keys="expandedKeys"
:default-checked-keys="checkedData"
/>
</div>
</div>
<template #footer>
<div class="dialog-footer">
<el-button @click="close">取消</el-button>
<el-button type="primary" @click="handleSubmit"> 确定 </el-button>
</div>
</template>
</el-dialog>
在这段代码中,el-dialog包含了角色名称显示、菜单权限操作按钮(展开 / 折叠、全选 / 全不选、父子联动)以及一个el-tree组件用于展示菜单树结构。el-tree通过绑定menudatas数据来渲染菜单节点,并通过各种属性配置其行为,如check-strictly控制是否严格父子联动,default-expanded-keys和default-checked-keys分别设置默认展开和选中的节点。
二、数据与功能实现
在<script setup>部分,我们定义了各种数据和函数来实现菜单权限配置的核心功能。
1. 引入依赖和定义数据
javascript
import { ref, provide, watchEffect, onMounted } from "vue";
import { roleMenusPermissionData } from "./simulatedData.js";
import { getDynamicRoutes } from "@/utils/getData.js";
const props = defineProps({
roleId: {
Type: Number,
required: true,
},
});
const treeProps = {
label: (data) => data.meta.title,
};
// 获取菜单树结构
const menudatas = ref([]);
const checkAll = ref(false); // 全选
const expandAll = ref(true); // 展开
const checkStrictly = ref(true); // 父子联动
我们引入了 Vue 的响应式数据函数ref,以及用于依赖注入的provide等。通过defineProps接收父组件传递的roleId,这在实际应用中可用于根据不同角色加载不同的菜单权限数据。treeProps定义了如何显示el-tree节点的标签,即通过data.meta.title。menudatas用于存储菜单树的数据,checkAll、expandAll和checkStrictly分别控制全选、展开和父子联动的状态。
2. 数据加载与监听
javascript
watchEffect(() => {
// 仅模拟页面效果使用,根据不同id获取不同的菜单权限
if (props.roleId == 1) {
} else {
}
});
onMounted(() => {
getDynamicRoutes().then((res) => {
menudatas.value = res;
});
});
watchEffect函数用于监听props.roleId的变化,这里只是简单的模拟,实际应用中可以根据不同的roleId从后端获取相应的菜单权限数据。onMounted钩子函数在组件挂载后执行,通过调用getDynamicRoutes函数从后端获取动态路由数据,并将其赋值给menudatas,从而渲染菜单树。
3. 全选 / 全不选功能实现
javascript
const handleCheckAllChange = (val) => {
const permissionIds = extractPermissionIds(menudatas.value);
if (val) {
treeRef.value.setCheckedKeys(permissionIds);
} else {
treeRef.value.setCheckedKeys([]);
}
};
handleCheckAllChange函数在全选 / 全不选复选框状态改变时触发。它首先通过extractPermissionIds函数获取所有菜单节点的id,然后根据复选框的状态,使用treeRef.value.setCheckedKeys方法设置el-tree的选中节点。
4. 展开 / 折叠功能实现
javascript
const expandedKeys = ref([]);
const treeRef = ref(null);
//展开、折叠
const handleExpandAllChange = (value) => {
expandAll.value = value;
let nodes = treeRef.value.store._getAllNodes();
if (expandAll.value) {
nodes.forEach((item) => {
item.expanded = expandedKeys.value;
});
} else {
nodes.forEach((item) => {
item.expanded =!expandedKeys.value;
});
}
};
handleExpandAllChange函数用于处理展开 / 折叠操作。它通过treeRef.value.store._getAllNodes()获取el-tree的所有节点,然后根据expandAll的值,遍历节点并设置其expanded属性,从而实现展开或折叠所有节点的效果。
5. 父子联动功能实现
javascript
// 父子联动
const handleCheckStrictlyChange = (val) => {
// 因为后端返回的id包括了父节点的id,父子联动时如果有父节点则默认会将所有子节点勾选,为了避免这种情况,所有需要把后台返回的父节点id筛出去
if (val) {
treeRef.value.setCheckedKeys(extractChildPermissionIds(menudatas.value));
}
};
handleCheckStrictlyChange函数在父子联动复选框状态改变时触发。当开启父子联动时,它通过extractChildPermissionIds函数获取所有子菜单节点的id,并使用treeRef.value.setCheckedKeys方法设置el-tree的选中节点,以确保在父子联动模式下,只勾选子菜单节点,避免因父节点勾选而自动勾选所有子节点的问题。
6. 提交功能实现
javascript
// 提交
const handleSubmit = () => {
// 将选中的id数组上传至后台接口,根据后端的要求,如果需要穿父节点,那checkedKeys和halfCheckedKeys都需要上传
const checkedKeys = treeRef.value.getCheckedKeys()
const halfCheckedKeys = treeRef.value.getHalfCheckedKeys()
console.log(
treeRef.value.getCheckedKeys(),
treeRef.value.getHalfCheckedKeys()
);
emits("close");
};
handleSubmit函数在用户点击确定按钮时触发。它通过treeRef.value.getCheckedKeys()和treeRef.value.getHalfCheckedKeys()获取已选中和半选中的节点id,然后可以将这些id数组上传至后端接口,完成菜单权限的配置更新。最后,通过emits("close")关闭弹窗。
三、样式调整
在<style lang="scss" scoped>部分,我们为el-tree的容器添加了一个简单的边框样式。
css
.containner {
border: 1px solid #d3d3d3;
}
通过这种方式,我们可以根据实际需求对菜单权限配置界面进行样式定制,提升用户体验。
通过以上步骤,我们成功地在 Vue 3 中搭建了一个功能齐全的菜单权限配置界面。这个界面不仅能够展示菜单树结构,还提供了全选 / 全不选、展开 / 折叠、父子联动以及提交配置等功能,满足了实际项目中菜单权限管理的需求。
完整代码实现请参考开源项目:vue3-pc-template
欢迎 Star 和 Fork 项目,一起构建更完善的权限管理体系!