路由守卫的使用案例------进入页面时进行值集加载
背景
项目里的前端项目是一个很大的项目,很多前端都在这个项目里开发,大概有三五个。而每个人都在自己开发的页面单独写了请求值集的方法,这就导致维护困难,代码量冗余。为何不把请求值集的方法统一起来做一个入口呢? 公司目前前端技术栈使用的是vue2
背景知识------值集是什么?
这个好像各家的叫法都不太一样,简单来说这东西就是key和value的合集。比如订单状态,以'已支付'状态为例,首先后端在真正保存数据到数据库的时候,不会真的保存一个中文字符串'已支付',而是会把它映射成一个自定义值,比如字符串'10'。后端提供的查询接口中,状态字段的值为'10',前端为了翻译成对应的中文值,就需要获取映射关系。 在数据库里,简化后的数据结构长这样。后端提供的查询接口关键词是值集代码。用值集代码查出对应的键值对集合:
值集代码 | 值集key | 值集value |
---|---|---|
ORDER_STATE | 10 | 待支付 |
ORDER_STATE | 20 | 已支付 |
(值集的典型应用------下拉框)
当前现状
由于这个前端项目混合了许多页面,好几个前端在同时写。虽然后端请求值集的接口是固定的,但是每个前端都在自己写的页面里额外写了一个函数来获取值集,造成了相当大的代码冗余,难以维护。所以打算参考之前大哥写的一个思路,用路由守卫的方式去请求值集。我们只需要维护一个页面→值集的map配置,新增页面的时候,在配置里添加对应的值机代码就行了
实现思路
设置一个自定义的路由守卫,在进入某一页面前(beforeEach钩子),根据页面的路由查找一个自定义的配置。再根据查找到的配置请求接口,将获取到的接口存入到localStorage或VueStore里。
看看代码
我们先自定义一个维护值集属性的js,这样后续我们新增页面需要使用新值集时,只需要修改这个配置文件,新增路由和值集代码就可以了,这样就做到了统一入口维护。
arduino
// value-set-config.js
let config = [
'/orderManage/list': ['ORDER_STATE'],
]
export default config
然后我们写一个js,这个js做数据处理,请求后端接口-转换数据格式-保存转换后数据格式至缓存 这部分各家都有各家的处理方法,代码也就只截取部分,做个大概展示了哈
typescript
// value-set.js
import { get } from '@/libs/axios';
import store from '../store';
import valueSetCode from './value-set-config'
// 数据格式化
let dataFormat = (data) => {
let result = {};
if (data && typeof (data.data) == 'object') {
for (var key in data.data) {
// result[key] = data.data[key].map(({ id, itemCode, itemName, setName, status }) => {
// return { id, itemCode, itemName, setName, status }
// });
result[key] = data.data[key].map((item) => {
return { ...item }
});
}
}
return result;
}
// 请求后端值集查询接口
let requestFn = (routerName, type = 'byRouter') => {
let url = OPTIONS.url;
if (url === null || OPTIONS.valueSetCodeObj === null) {
throw new Error('value-set OPTIONS 缺少配置')
}
// axios请求
return get(url)(getParams(routerName));
}
//router 全局路由获取
export let getValueSetByRouter = async (routerName, router) => {
let { data } = await requestFn(routerName)
if (!data.data) {
localStorage.setItem('codeSet', '{}');
return;
}
let currentRouter = router.currentRoute.name;
localStorage.setItem('codeSet', JSON.stringify(dataFormat(data)));
return dataFormat(data);
}
// 根据路由名称,读取配置,并请求后端接口,保存请求数据至VueStore
let getValueSetCode = async (routerName, router) => {
console.log(routerName,'routerName')
// 解决初始化值集报错
let initCodeValue = () => {
let obj = {};
if (!valueSetCode[routerName]) {
return 'no result';
}
valueSetCode[routerName].forEach(key => {
obj[key] = [];
})
store.dispatch('setValueSetCode', obj)
}
if (initCodeValue() === 'no result') return;
let result = await getValueSetByRouter(routerName, router);
// console.log(result)
store.dispatch('setValueSetCode', result)
}
VueStore的定义比较常规,就是最基础的取值设值,就不展示了。 最后,我们定义一个钩子函数,在路由至页面之前,调用之前定义好的接口,根据路由路径请求值集数据,并保存到缓存中
javascript
// router/index.js
/**
* 省略若干无关代码
**/
// 路由配置
const RouterConfig = {
mode: 'hash',
routes: routers
};
export const router = new VueRouter(RouterConfig);
export default router;
// 钩子函数
router.beforeEach((to, from, next) => {
// 省去若干无关代码
getValueSetCode(to.name, router) // 请求值集
// 省略若干无关代码
});
在main.js引入并使用自定义的router即可
javascript
// main.js
import Vue from 'vue'
import { router } from './router/index'
/**
* 省略若干无关代码
**/
var vm = new Vue({
... // 省略无关代码
el: '#app',
router,
... // 省略无关代码
},
})
export default vm
赛后总结
对于值集的加载,我们使用了统一入口进行处理,分成了以下几个步骤:
- 使用一个map来保存路由与请求值集之间的映射关系
- 自定义一个方法,这个方法的入参是 路由路径,实现的功能是请求后端的值集查询接口,并将请求值保存在缓存中
- 自定义路由守卫,在路由至指定页面前,请求步骤2中定义的方法,这样页面中就能获取到对应的值集了
xml
// 指定页面中使用store中的值集
// 使用案例一则
<template>
<!-- 省去若干代码 -->
<Form label="订单状态">
<Select v-model="orderForm.orderState" disabled>
<Option
v-for="(item, index) in valueSet.ORDER_STATE"
:value="item.itemCode"
:key="index"
>
{{ item.itemName }}
</Option>
</Select>
</Form >
<!-- 省去若干代码 -->
</template>
<script>
import { mapGetters } from "vuex";
export default {
data(){
return{
orderForm:{ orderState:'' }
}
},
computed:{
valueSet() {
return this.$store.state.codeValue.valueSet;
}
},
...
}
</script>