路由徹底由後端返回css
children: [ // 子路由放入children屬性中
{
children: []
component: "views/index/content/index"
id: 5
meta: {isLogin: 1, icon: "el-icon-postcard", title: "項目概覽", isShow: 1}
name: "/home/index/content"
path: "/home/index/content"
}
]
component: "views/index" // 對應頁面的文件地址
id: 3 // 惟一屬性
// isLogin判斷是否須要登陸訪問,isShow判斷是否顯示在導航欄上,title展現導航欄名字
meta: {isLogin: 1, icon: "el-icon-date", title: "整體概況", isShow: 1}
name: "index" // 組件名
path: "index" // 路由地址
複製代碼
<template>
<div id="app">
<router-view />
</div>
</template>
複製代碼
根據父子路由的配置,子路由必需要在有rout-view狀況下才能切換,因此須要在首頁設置導航欄,還有導航欄路由對應的頁面vue
相似這種佈局ios
<template>
<div class="main">
<div class="main-left">
<!-- 放置導航欄菜單組件 -->
</div>
<div class="main-right">
<!-- 右邊內容 -->
<div class="main-right-container">
<router-view></router-view>
</div>
</div>
</div>
</template>
複製代碼
引入vuex數據vuex
computed: {
...mapGetters([
'menuList'
])
},
methods: {
...mapActions([
'getMenuList',
]),
}
複製代碼
// 登陸後觸發的函數
login() {
let url='/你的api地址';
let reqData={};
let res = await Http.axiosPost(url, reqData); // 這裏使用axios,晚點出一篇axios配置到原型鏈的文章
if (res.code === 200) {
// 存登陸狀態
localStorage.setItem('Flag','isLogin');
// 存登陸token
localStorage.setItem('TOKEN',res.obj);
// 調用mapGetters,查看vuex中是否有路由數據
let code = await this.getMenuList();
if(code === 200){ // 存在路由
// 跳轉導航欄首頁
let Path= this.menuList[0].children[0].children[0].path
this.$router.push({path: Path})
}else{ // 不存在路由,說明配置問題了
console.log('路由獲取失敗', code)
MessageBox({
title: '警告',
message: '導航配置問題,請聯繫管理員',
callback: action => { // 回調函數
localStorage.clear(); // 清除緩存數據
next({path: '/login', replace: true }) // 跳轉登陸
}
})
}
}
}
複製代碼
import Vue from 'vue'
import Vuex from 'vuex'
import { normalRouter } from '../router'
import createLogger from 'vuex/dist/logger'
Vue.use(Vuex)
// 設置只有在開發環境的時候纔打印日誌
const debug = process.env.NODE_ENV !== 'production'
const state = {
menuList: '1'
}
const getters = {
menuList: state => state.menuList
}
const mutations = {
setMenuList (state, value) {
// 存入數據
state.menuList = menus;
// 加入登陸頁面等一級路由
menus = menus.concat(normalRouter)
// matcher是用來解決 Duplicate named routes definition 報錯解決路由重複
VueRouter.matcher = new Router().matcher
// 錯誤頁面要最後添加,否則訪問動態的路由會先出現404
menus.push({
path: '*', // 頁面不存在的狀況下會跳到404頁面
redirect: '/error',
})
VueRouter.addRoutes(menus)
}
}
const actions = {
// 獲取動態路由
async getMenuList({commit}) {
// 經過接口獲取路由數據
let url='/你的api地址';
let reqData={};
let res = await Http.axiosPost(url, reqData); // 這裏使用axios,晚點出一篇axios配置到原型鏈的文章
if(res.code === 200){ // 成功
// res.obj[0].component = "views/homepage"
let menus = needRoutes(res.obj) // 生成路由信息
// 確認路由層級,一級路由只有一個,往下的頁面都是子路由
commit('setMenuList', [{
path: "/home",
component:(resolve) =>{
require(['@/views/homepage'],resolve)
},
meta: { isLogin: true // 添加該字段,表示進入這個路由是須要登陸的
},
children:menus
}])
return res.code
} else { // 失敗
return res.code
}
}
}
// 生成路由數據
let needRoutes = (data) => {
// 判斷是不是數組
if (!Array.isArray(data)) {
return new TypeError('arr must be an array.');
}
let arr = formatComponent(data)
return arr;
}
// 遞歸函數,用來對組件進行異步渲染
let formatComponent = (data) => {
for (let obj of data) {
const component = obj.component
// 把後臺返回的路由參數,拼接路徑
obj.component = resolve => { require(['@/' + component], resolve) }
if (obj.children.length > 0) { // children有長度,說明有子路由
formatComponent(obj.children)
}
}
return data
}
const store = new Vuex.Store({
state,
getters,
mutations,
actions,
strict: debug,
plugins: debug ? [createLogger()] : []
})
export default store
複製代碼
// 配置一級路由配置和重定向
// login頁面和error頁面是不須要登陸判斷的,能夠放在默認路由內
export const normalRouter = [
{
path: "/",
redirect: '/login',
// meta: {
// isLogin: false, // 添加該字段,表示進入這個路由是須要登陸的
// title:'登陸'
// }
},
{
path: "/login",
name: "Login",
// components:require('./views/login'),
component: resolve => require (['@/views/login'], resolve),
meta: {
isLogin: false, // 添加該字段,表示進入這個路由是須要登陸的
title:'登陸'
}
},
{
path: "/home",
redirect: '/home/index',
},
{
path: "/error",
name: "error",
component: error,
meta: {
isLogin: false, // 添加該字段,表示進入這個路由是須要登陸的
title:'錯誤'
}
},
]
複製代碼
let router = new Router({
mode: "history",
base: process.env.BASE_URL,
routes:normalRouter
});
複製代碼
// 由於用到了element ui,因此要引入一下
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
Vue.use(ElementUI)
router.beforeEach( async (to, from, next) => {
console.log('before路由', to);
// 獲取緩存的登陸狀態
let hasLogin = localStorage.getItem("Flag")
// 有登陸狀態
if (hasLogin) {
console.log('state', store.state.menuList.length, to, from)
// 判斷vuex中是否有存入路由數據
if (store.state.menuList.length === 0) {
// 進入到這一步用戶已經登陸過,可是又刷新了瀏覽器,致使路由清空了,因此要在vuex中從新請求路由
let res = await store.dispatch('getMenuList')
// code 不爲200 時候,說明路由接口報錯,須要從新登陸
if (res !== 200) {
// element 提示框
MessageBox({
title: '警告',
message: '導航配置問題,請聯繫管理員',
callback: action => { // 回調函數
// 清除登陸緩存數據
localStorage.clear();
// 跳轉登陸頁
next({path: '/login', replace: true })
}
})
} else { // 有路由數據
// router.addRoutes是異步的,因此把全局的跳轉 *也動態添加了,同時使用 next({ ...to, replace: true })從新載入
next({...to, replace: true })
}
}
if (to.name === 'Login') { // 已經登陸過,可是訪問的是login,強制跳轉至首頁
// 這裏設置的是vuex中首個導航欄的path地址
next({
path: store.state.menuList[0].children[0].children[0].path,
})
} else { // 正常跳轉
next()
}
} else { // 沒有登陸,則強制跳轉登陸頁
console.log('to', to)
// 沒有登陸想訪問其餘頁面,跳轉至
if (to.name !== 'Login') {
next({
path: '/login',
})
} else {
next()
}
}
})
複製代碼
vue權限路由實現方式總結element-ui