Vben框架使用中遇到的问题
公司使用vben框架搭建了一套后台管理系统,集成了登陆、菜单路由、权限、数据字典、短信发送、app登陆、websocket、工作流等,实现动态更改首页样式,主题配色,枚举字典值等。
vben是一个封装的特别详细的框架,也是第一次使用vue3+Ts去编写代码,这中间遇到了无数坑和复杂的知识点,说难也不算难,就是上手比较慢,但是看懂了以后又能很快去吸收。
以下是我遇到的一些问题和在vben中没有直接搜索到的使用方法。
首先,贴一个vben官网地址:http://doc.vvbin.cn/components/introduction.html
1. 菜单管理+路由
vben提供了三种角色权限路由模式,
export enum PermissionModeEnum {
// 角色权限
ROLE = "ROLE",
// 后端
BACK = "BACK",
// 路由映射
ROUTE_MAPPING = "ROUTE_MAPPING",
}
我们一般会采取BACK
,即当前的路由都由后端返回,前端只需要通过接口将后端传来的路由表渲染在路由中即可,这一步可以在项目的src\store\modules\permission.ts
文件中更改。
try {
await this.changePermissionCode();
//获取路由
routeList = (await getRouterList()) as AppRouteRecordRaw[];
} catch (error) {
console.error(error);
}
//将当前后端返回的数据处理成渲染路由的格式 这里可以去看下源码,vben封装的
routeList = transformObjToRoute(routeList);
const backMenuList = transformRouteToMenu(routeList);
this.setBackMenuList(backMenuList);
routeList = filter(routeList, routeRemoveIgnoreFilter);
routeList = routeList.filter(routeRemoveIgnoreFilter);
routeList = flatMultiLevelRoutes(routeList);
// routes = [PAGE_NOT_FOUND_ROUTE, ...routeList];
routes = [PAGE_NOT_FOUND_ROUTE, ...asyncRoutes, ...routeList];
这里的getRouterList()就是后端接口,routeList经过一系列方法处理变成可渲染在左侧菜单的路由数据。
因为此时系统中的路由页面都是通过后端接口返回的,如果前端仅仅在开发期画页面或者在后端服务没有启动时想要赶页面的话,可以将这行代码:
// 前端引入的路由组件
routes = filter(asyncRoutes, routeFilter);
routes = routes.filter(routeFilter);
routeList = [...routeList, ...routes];
加在 routeList = transformObjToRoute(routeList);
之后,然后在src\router\routes\modules
下新建你想要的路由
2. axios方法的封装
项目中统一代理写在vite.config.ts文件中,这里通过/api去代理后端地址。
server: {
proxy: {
"/api": {
target: "http://192.168.0.18:9000",
changeOrigin: true,
ws: true,
rewrite: (path) => path.replace(new RegExp(`^/api`), ""),
// only https
// secure: false,
},
},
},
axios请求封装的位置在src\utils\http\axios\index.ts
中,这里处理了请求发送、接收、拦截等方法,以及应对后端返回状态码的处理。我这里是直接将data.data返回
我们还可以根据文件中封装的axios,在单独写接口地址的地方进行特别处理,比如这个参数isTransformResponse(是否对返回数据进行处理)
。
因为我们项目中后端返回分页的格式是这样的,分页信息和data是同一层级,为了应对项目中BasicTable中api的写法的统一,我们就直接将data作为返回值,如果遇到了不需要直接返回data的场景,则需要在接口中添加这个参数为false ,例如:
export function getNoticePageRes(params: NoticePageReqVO) {
return defHttp.get(
{ url: "/notification/notice/v1/page", params },
{ isTransformResponse: false }
);
}
如果前端想要进行模拟接口,可以在
src\utils\http\axios\index.ts
最下方加入这行代码,模拟apifox或者第三方接口工具模拟的接口,这样我们就可以在项目中使用两种接口了,而不需要更改/api代理 。
// 本地APIFOX模拟的数据
export const otherHttp = createAxios({
requestOptions: {
apiUrl: "http://127.0.0.1:4523/m1/3088047-0-default", // 默认将prefix 添加到url
},
});
3. 关于BasicTable使用
我一般是使用组件自带的 useTable 可以方便使用表单,
const [registerTable, { reload}] = useTable({
title: "账户列表",
api: getUserPage,
rowKey: "id",
columns,
formConfig: {
labelWidth: 120,
schemas: searchFormSchema,
autoSubmitOnEnter: true,
},
useSearchForm: true,
showTableSetting: true,
handleSearchInfoFn(info) {
return info;
},
actionColumn: {
width: 200,
title: "操作",
dataIndex: "action",
},
});
- 分页列表:
全局:src\settings\componentSetting.ts
中更改表格配置,fetchSetting的pageField、sizeField、listField、totalField,以及分页默认显示条数等
局部:可以直接将全局的对象fetchSetting
写在useTable中覆盖全局,还可以用pagination
去配置分页列表 - 传参修改:
如果接口传参除了分页和当前定义的searchFormSchema的参数,我们可以在handleSearchInfoFn()
这个方法里添加参数,也可以通过beforeFetch()
处理。 - 返参处理:
如果想要对接口返回的参数进行处理可以通过afterFetch()
函数
4.权限操作
项目中封装了权限的相关指令,建议在用户登录后返回当前角色所有的权限列表,然后在你想添加的按钮或者组件中写上指令v-auth="['system:step-package:create']"
,就表明当前角色有system:step-package:create
才能看到这个按钮。
注意:我尝试过直接加在引入的子组件中不生效,报了如下Runtime directive used on component with non-element root node. The directives will not function as intended.
警告,查阅后发现需要在外层加上div。
在table中的action使用:
:actions="[
{
icon: IconEnum.EDIT,
label: '编辑',
auth: 'system:user:update',
onClick: handleEdit.bind(null, record),
},
]"