业务常识

本文最后更新于:8 个月前

项目开发过程中的技巧与知识,如目录规范、权限管理逻辑……

业务常识

一、目录划分规范

在开发过程中,严格遵循一套规范,可以大大提高我们的效率,不仅开发过程中能快速准确找到相关文件,在日后维护过程中也能够对项目结构一目了然,节省维护的时间成本。

在划分项目结构时,需要遵循的一些基本原则:

  • 文件夹与文件 语义一致性
  • 模块内部紧耦合
  • 单一入口/出口
  • /src外的文件不应该被引入

文件夹与文件 语义一致性

比如每个Vue项目都会有一个路由模块,比如叫pagesviews文件夹,那么这个文件夹里就应该只放路由模块,而不包含其它与路由模块无关的文件,这样做的好处是可以从pages文件夹一眼看到项目所有路由。

模块内部紧耦合

模块的特有组成部分(公共组成部分另当别论),和模块放置在一个文件夹下,这样需要移植单个模块的时候,可以实现快速移植。而且在模块内部引用时,不会收到外部路径变化的影响,避免了后续变化带来的影响。

单一入口/出口

举个例子,在pages文件夹里面存在一个seller文件夹,这时候seller 文件夹应该作为一个独立的模块由外部引入,并且 seller/index.js 应该作为外部引入 seller 模块的唯一入口。

这样做的好处是,无论seller模块内部的文件夹内容有多复杂,外部引用的时候,只需要关注入口文件index.js即可。这样就很好的实现了隔离,如果后续有重构需求,你就会发现这种方式的优点

/src 外的文件不应该引入

Vue CLI脚手架已经帮我划分好了项目结构,/src下放置项目需要的资源jscssvue等,/src外放置一些项目配置、环境、依赖文件。这样做的好处是方便划分管理项目代码文件、和配置文件

二、权限管理

什么是权限

对特定资源的访问许可,确保用户只能访问到允许被分配的资源

权限控制的思路

  • 路由方面,用户只能看到自己有权访问的导航菜单,因此只能访问有权访问的地址
  • 视图方面,用户只能看到有权浏览的内容和有权操作的控件
  • 请求控制,对发出的请求进行身份验证

前端权限控制可以分为以下4个方面

  • 接口权限
  • 路由权限
  • 菜单权限
  • 按钮权限

接口权限

接口权限目前一般采用jwt的形式来验证,没有通过的话一般返回401,跳转到登录页面重新进行登录。登录完拿到token,将token存起来,通过axios请求拦截器进行拦截,每次请求的时候头部携带token

路由权限

方案一:挂载全部路由,在路由上标记对应的权限信息,每次跳转路由前(用路由导航守卫)做校验

1
2
3
4
5
6
7
8
9
const routerMap = [
{
....
meta: {
title: 'permission',
icon: 'lock',
roles: ['admin', 'editor'] // you can set roles in root nav
}
}]

弊端:

  • 有可能加载很多不必要的路由,造成性能影响
  • 每次路由跳转都需要做权限判断

方案二;初始化挂载公共路由,登陆后在全局路由守卫里通过addRoutes()动态添加权限路由

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
router.beforeEach((to,from,next)=>{
...
if (store.getters.roles.length === 0){
store.dispatch('GetUserInfo').then(res => { // 拉取user_info
const roles = res.data.roles // note: roles must be a array! such as: ['editor','develop']
store.dispatch('GenerateRoutes', { roles }).then(() => { // 根据roles权限生成可访问的路由表
router.addRoutes(store.getters.addRouters) // 动态添加可访问路由表!!
next({ ...to, replace: true }) // hack方法 确保addRoutes已完成
})
}).catch((err) => {
...
})
}
...
})

菜单权限

可以理解成,将导航菜单与路由解耦合

方案一:路由由前端定义,菜单由后端返回,通过路由的name字段与菜单的name字段匹配

1
2
3
4
5
6
//前端定义路由信息
{
name: "login",
path: "/login",
component: () => import("@/pages/Login.vue")
}

怎么生成菜单的过程不详,但是给的案例中,即使是动态生成的菜单,在每次导航跳转时,依旧对路由的name和菜单的name进行了一个比对,对上了才给予放行访问。

弊端:菜单和路由需要一一对应,尤其是name属性,需要前后端严密对接

方案二:菜单和路由都由后端返回,前端只定义路由组件

1
2
3
4
5
6
7
//前端统一定义路由组件
const Home = () => import("../pages/Home.vue");
const UserInfo = () => import("../pages/UserInfo.vue");
export default {
home: Home,
userInfo: UserInfo
};
1
2
3
4
5
6
7
8
9
10
11
12
13
//后端路由组件返回以下格式
[
{
name: "home",
path: "/",
component: "home"
},
{
name: "home",
path: "/userinfo",
component: "userInfo"
}
]

注意:在将后端返回路由通过addRoutes动态挂载之间,需要将数据处理一下,将component字段换为真正的组件。如果有嵌套路由,后端功能设计的时候,要注意添加相应的字段,前端拿到数据也要做相应的处理

弊端:前后端配合要求高

按钮权限

自定义指令进行按钮权限判断

第一步,配置路由

1
2
3
4
5
6
7
8
9
{
path: '/permission',
component: Layout,
name: '权限测试',
meta: {
btnPermissions: ['admin', 'supper', 'normal'] //页面需要的权限
},
...
}

第二步,自定义权限鉴定指令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import Vue from 'vue'
/**权限指令**/
const has = Vue.directive('has', {
bind: function (el, binding, vnode) {
// 获取页面按钮权限
let btnPermissionsArr = [];
if(binding.value){
// 如果指令传值,获取指令参数,根据指令参数和当前登录人按钮权限做比较。
btnPermissionsArr = Array.of(binding.value);
}else{
// 否则获取路由中的参数,根据路由的btnPermissionsArr和当前登录人按钮权限做比较。
btnPermissionsArr = vnode.context.$route.meta.btnPermissions;
}
if (!Vue.prototype.$_has(btnPermissionsArr)) {
el.parentNode.removeChild(el);
}
}
});
// 权限检查方法
Vue.prototype.$_has = function (value) {
let isExist = false;
// 获取用户按钮权限
let btnPermissionsStr = sessionStorage.getItem("btnPermissions");
if (btnPermissionsStr == undefined || btnPermissionsStr == null) {
return false;
}
if (value.indexOf(btnPermissionsStr) > -1) {
isExist = true;
}
return isExist;
};
export {has}

第三步,只需要在要鉴别权限的按钮上使用v-has指令即可

1
<el-button @click='editClick' type="primary" v-has>编辑</el-button>

参考文章:面试官:vue要做权限管理该怎么做?如果控制到按钮级别的权限怎么做? | web前端面试 - 面试官系列 (vue3js.cn)

三、需求分析

区分用户需求、功能需求、非功能需求:

【用户需求】针对的是人,描述用户想做某件事所遇到的问题,或想满足的愿望
【功能需求】针对的是产品,描述产品如何解决用户所遇到的问题,或如何满足用户的欲望,是方式方法。
【非功能需求】为满足用户(业务)需求而必须具有的除功能需求以外的特性,包括安全性、可靠性、互操作性

四、架构图

区分不同类型的架构:

【应用架构】对整个系统实现的总体上的架构,需要指出系统的层次、系统开发的原则、系统各个层次的应用服务。

例如,下图就将系统分为数据层、服务层、通讯层、展现层,并细分写明每个层次的应用服务。

img

【技术架构】对接应用架构的技术需求,并根据识别的技术需求,进行技术选型,把各个关键技术和技术之间的关系描述清楚。

五、组件化思想

组件化思想在各种语言、框架、技术中的体现

  • HTML —— Web Component(正在推进)
  • CSS —— @import url()
  • JavaScript —— ES Module、类
  • Vue —— SFC单文件组件

组件化思想的核心是:

  • 重复使用代码,提高利用率,降低冗余率,也是提升效率
  • 提高代码鲁棒性,小模块相比于大项目更不容易出错(或者说更容易排查出错误)

业务常识
http://timegogo.top/2022/10/07/前端工程化/业务常识/
作者
丘智聪
发布于
2022年10月7日
更新于
2023年7月16日
许可协议