## vue鉴权的实现
### 路由的动态注入
#### 递归遍历路由
**静态路由**
```
// 静态路由
export const StaticRouterMap = [
{
path: '/login',
component: login,
meta: { title: '管理员登录' },
hidden: true
},
{
path: '/user',
component: userLogin,
redirect: '/user/userlogin',
name: 'user',
hidden: true,
children: [
{
path: 'userLogin',
component: () => import('@/views/userLogin/components/login'),
meta: { title: '商户登录' }
},
{
path: 'userRegistry',
component: () => import('@/views/userLogin/components/registry'),
meta: { title: '商户注册' }
}
]
},
{
path: '/',
component: Layout,
redirect: '/dashboard',
name: 'dashboard',
children: [
{
path: 'dashboard',
component: () => import('@/views/dashboard/index'),
meta: { title: '根目录', icon: 'dashboard', affix: true }
}
]
},
{
path: '/404',
component: () => import('@/views/404'),
hidden: true
}
]
export default new Router({
mode: 'history',
scrollBehavior: () => ({ y: 0 }),
routes: StaticRouterMap
})
```
#### 权限数据
```
[{
"id": 1,
"name": "Nested",
"code": null,
"description": null,
"url": "/nested",
"generatemenu": 0,
"sort": 0,
"parentId": null,
"permName": null,
"redirect": "/nested/menu1",
"title": "Nested",
"icon": "nested",
"children": [{
"id": 2,
"name": "Menu1",
"code": null,
"description": null,
"url": "menu1",
"generatemenu": 0,
"sort": 0,
"parentId": 1,
"permName": null,
"redirect": "",
"title": "Menu1",
"icon": "menu1",
"children": [{
"id": 4,
"name": "Menu1-1",
"code": null,
"description": null,
"url": "menu1-1",
"generatemenu": 0,
"sort": 0,
"parentId": 2,
"permName": null,
"redirect": "",
"title": "Menu1-1",
"icon": "",
"children": null
}, {
"id": 5,
"name": "Menu1-2",
"code": null,
"description": null,
"url": "menu1-2",
"generatemenu": 0,
"sort": 0,
"parentId": 2,
"permName": null,
"redirect": "",
"title": "Menu1-2",
"icon": "",
"children": null
}]
}, {
"id": 3,
"name": "Menu2",
"code": null,
"description": null,
"url": "menu2",
"generatemenu": 0,
"sort": 0,
"parentId": 1,
"permName": null,
"redirect": "",
"title": "Menu2",
"icon": "menu2",
"children": null
}]
}]
```
#### 组件
异步加载
```
export default file => {
return map[file] || null
}
const map = {
Nested: () => import('@/views/layout/Layout'),
Menu1: () => import('@/views/nested/menu1/index'),
'Menu1-1': () => import('@/views/nested/menu1/menu1-1'),
'Menu1-2': () => import('@/views/nested/menu1/menu1-2')
}
```
#### 递归遍历路由
```
import _import from '../router/_import' // 获取组件的方法
/**
* 生成路由
* @param {Array} routerlist 格式化路由
* @returns
*/
export function addRouter(routerlist) {
const router = []
routerlist.forEach(e => {
let e_new = {
path: e.url,
name: e.name,
component: _import(e.name)
}
if (e.children) {
e_new = Object.assign({}, e_new, { children: addRouter(e.children) })
}
if (e.redirect) {
e_new = Object.assign({}, e_new, { redirect: e.redirect })
}
if (e.generatemenu == 0) {
e_new = Object.assign({}, e_new, { hidden: true })
}
if (e.icon !== '' && e.title !== '') {
e_new = Object.assign({}, e_new, {
meta: { title: e.title, icon: e.icon }
})
} else if (e.title !== '' && e.icon === '') {
e_new = Object.assign({}, e_new, { meta: { title: e.title }})
}
router.push(e_new)
})
return router
}
```
#### 处理后的路由
```
[{
"name": "Nested",
"redirect": "/nested/menu1",
"children": [{
"name": "Menu1",
"children": [{
"name": "Menu1-1",
"children": null,
"path": "menu1-1",
"meta": {
"title": "Menu1-1"
}
}, {
"name": "Menu1-2",
"children": null,
"path": "menu1-2",
"meta": {
"title": "Menu1-2"
}
}],
"path": "menu1",
"meta": {
"title": "Menu1",
"icon": "menu1"
}
}, {
"name": "Menu2",
"children": null,
"path": "menu2",
"component": null,
"meta": {
"title": "Menu2",
"icon": "menu2"
}
}],
"path": "/nested",
"meta": {
"title": "Nested",
"icon": "nested"
}
}]
```
#### ### (核心)合并路由
```
import router from './router'
import store from './store'
import { getToken, removeToken } from './utils/auth'
import NProgress from 'nprogress' // Progress 进度条
import 'nprogress/nprogress.css' // Progress 进度条样式
import { Message } from 'element-ui'
import { getRouter } from './api/login'
import { addRouter } from './utils/addRouter'
const whiteList = ['/login']
var data = false // 本次demo用变量凑合一下,项目里面应该放到vuex内
router.beforeEach((to, from, next) => {
NProgress.start()
if (getToken()) {
// 判断cookice是否存在 不存在即为未登录
if (to.path !== '/login') {
if (data) {
// 获取了动态路由 data一定true,就无需再次请求 直接放行
next()
} else {
// data为false,一定没有获取动态路由,就跳转到获取动态路由的方法
gotoRouter(to, next)
}
} else {
Message({ message: '您已经登录', type: 'info' })
next('/')
}
} else {
data = false
if (whiteList.indexOf(to.path) !== -1) {
// 免登陆白名单 直接进入
next()
} else {
if (to.path !== '/login') {
// 重定向到登录页面 不能这么写 因为假如之前的角色是 管理员页面 后又登陆了非管理员 重定向的页面就可能不存在,就会导致404
// next(`/login?redirect=${to.path}`)
next('/login')
} else {
next()
}
}
}
})
router.afterEach(() => {
NProgress.done() // 结束Progress
})
function gotoRouter(to, next) {
getRouter(store.getters.token) // 获取动态路由的方法
.then(res => {
console.log('解析后端动态路由', res.data.data)
const asyncRouter = addRouter(res.data.data) // 进行递归解析
// 一定不能写在静态路由里面,否则会出现,访问动态路由404的情况.所以在这列添加
asyncRouter.push({ path: '*', redirect: '/404', hidden: true })
return asyncRouter
})
.then(asyncRouter => {
router.addRoutes(asyncRouter) // vue-router提供的addRouter方法进行路由拼接
data = true // 记录路由获取状态
store.dispatch('setRouterList', asyncRouter) // 存储到vuex
store.dispatch('GetInfo')
next({ ...to, replace: true }) // hack方法 确保addRoutes已完成
})
.catch(e => {
console.log(e)
removeToken()
})
}
```
#### **Vuex内部的逻辑**
```
import { StaticRouterMap } from '../../router/index'
state: {
//.....
RouterList: [] // 动态路由
},
mutations: {
set_router: (state, RouterList) => {
state.RouterList = RouterList
}
},
action: {
// 动态设置路由 此为设置设置途径
setRouterList({ commit }, routerList) {
commit('set_router', StaticRouterMap.concat(routerList)) // 进行路由拼接并存储
},
}
```
#### 挂载路由
```
computed: {
// ....
routes() {
return this.$store.getters.routerList
},
// ....
}
```
- css用法技巧
- 阴影被后面div遮挡
- 绘制一个三角形
- 图像的灰白处理
- 一切居中
- 禁用鼠标事件
- 模糊文本
- 字体省略号
- 垂直居中
- box投影
- css动画
- javaScript常见工具封装
- 地址栏参数获取
- 日期格式化
- Ajax
- scroll
- 缓动函数
- 事件绑定
- 阻止冒泡和默认行为
- 伪数组正常化
- 日期生成
- 拷贝
- javaScript基本知识
- javaScript基本知识
- javascript常见代码块
- vue常见问题
- 获取参数
- vue常见问题/vue混入
- v-html指令问题集锦
- 正则获取html中所有的中文字符
- 时间格式化
- 监听路由的变化
- vue移动端滑动事件
- vue移动端图片点击放大
- 打包后背景图片404的问题
- webpack打包后部分样式失效
- IE的兼容问题
- post请求后台无法接受参数
- 验证码
- vue开启Gzip报错
- v-html修改样式
- app.css文件过大
- vue中中使用iframe
- babel对es6编译不彻底 出现ie不兼容的问题
- vue单页应用优化
- 吸顶问题
- 跨域session无法共享
- 登陆返回上一页
- axois中使用delete数据传递问题
- 监听数组对象数组中的属性
- webpack
- webpack基本使用
- webpack打包删除注释
- js插件
- 轮播图
- 面向对象模板
- 左滑右滑
- 存储
- appcan
- appcan
- js深入研究
- 数组的参数传递问题
- 采用jquery的方法载入公共页面后出现闪烁的问题
- html拼接无法绑定事件
- 吸顶问题
- async配合promise使用
- flutter
- 模拟器加载报错
- 底部导航实现
- 模拟器出现错误
- flutter在idea下的快捷键
- flutter学习笔记
- 设计模式
- 观察者模式
- nest
- nest基本说明
- nest错误处理
- vue高级
- 动态注入路由
- nest实战
- 一项目准备
- window
- 端口进程被占
- mis包
- reactNative
- react-native-router-flux
- esLint
- eslint
- Cesium