天天看點

撸一個基于VUE的WEB管理背景(五)路由管理與Layout

api server已經有一個最基本的架構了,我們回到前端,開始制作一個使用者管理界面吧。

路由管理與Layout

從main.js可以看到渲染的入口是App.vue

import App from './App'
new Vue({
  el: '#app',
  router,
  store,
  i18n,
  render: h => h(App)
})
           

App.vue裡的模闆很簡單,就是一個router-view

<template>
  <div id="app">
    <router-view />
  </div>
</template>
           

結合之前分析過的permission.js,中間有個白名單:

如果是未登入使用者(判斷依據就是store中沒有token),通路的url又不在這個白名單中,就強行跳轉到login頁面

對于已經登入過,但store中還沒有使用者角色資訊的情況,先調用info接口擷取角色資訊,根據添加動态路由配置,最後在将頁面路由到指定的url

const { roles } = await store.dispatch('user/getInfo')
  const accessRoutes = await store.dispatch('permission/generateRoutes', roles)
  router.addRoutes(accessRoutes)
  next({ ...to, replace: true })
           

現在我們知道前端的路由配置都是在store/permission.js中的generateRoutes中實作的,檢視相關代碼,generateRoutes會根據使用者角色生成對應的動态路由規則,最後将這些規則與constantRoutes中定義的靜态規則合并到一起。

const mutations = {
  SET_ROUTES: (state, routes) => {
    state.addRoutes = routes
    state.routes = constantRoutes.concat(routes)
  }
}

const actions = {
  generateRoutes({ commit }, roles) {
    return new Promise(resolve => {
      let accessedRoutes
      if (roles.includes('admin')) {
        accessedRoutes = asyncRoutes || []
      } else {
        accessedRoutes = filterAsyncRoutes(asyncRoutes, roles)
      }
      commit('SET_ROUTES', accessedRoutes)
      resolve(accessedRoutes)
    })
  }
}
           

constantRoutes和asyncRoutes都是在router/index.js中定義的,router元件也是在這裡初始化的,可以看出,初始化時隻配置了靜态規則:

const createRouter = () => new Router({
  // mode: 'history', // require service support
  scrollBehavior: () => ({
    y: 0
  }),
  routes: constantRoutes
})

const router = createRouter()
           

constantRoutes靜态規則是一個大的數組,包含了url和對應view組建的映射關系

export const constantRoutes = [{
    path: '/redirect',
    component: Layout,
    hidden: true,
    children: [{
      path: '/redirect/:path*',
      component: () => import('@/views/redirect/index')
    }]
  },
  {
    path: '/login',
    component: () => import('@/views/login/index'),
    hidden: true
  },
           

asyncRoutes也是類似的數組,隻不過額外增加了一些通路控制資訊

export const asyncRoutes = [
    path: '/permission',
    component: Layout,
    redirect: '/permission/page',
    alwaysShow: true, // will always show the root menu
    name: 'Permission',
    meta: {
      title: 'permission',
      icon: 'lock',
      roles: ['admin', 'editor'] // you can set roles in root nav
    },
    children: [{
        path: 'page',
           

大概了解一下前端路由生成機制,我們發現幾乎所有路由都指向了Layout元件,繼續檢視Layout源碼layout/index.vue,這個元件是整個頁面布局的入口,左邊的siderbar,頂部的navbar,内容區的app-main,以及右邊的浮動設定按鈕right-panel。

<template>
  <div :class="classObj" class="app-wrapper">
    <div v-if="device==='mobile'&&sidebar.opened" class="drawer-bg" @click="handleClickOutside" />
    <sidebar class="sidebar-container" />
    <div :class="{hasTagsView:needTagsView}" class="main-container">
      <div :class="{'fixed-header':fixedHeader}">
        <navbar />
        <tags-view v-if="needTagsView" />
      </div>
      <app-main />
      <right-panel v-if="showSettings">
        <settings />
      </right-panel>
    </div>
  </div>
</template>
           

跟進看一下layout/components/AppMain.vue的實作,發現他的html模闆裡又包含了一個router-view,這就能讓我更好地了解嵌套路由的配置了。

<template>
  <section class="app-main">
    <transition name="fade-transform" mode="out-in">
      <keep-alive :include="cachedViews">
        <router-view :key="key" />
      </keep-alive>
    </transition>
  </section>
           
撸一個基于VUE的WEB管理背景(五)路由管理與Layout

了解Layout的結構,就可以知道,layout/components/siderbar/會根據路由規則實作siderbar中的菜單項,layout/components/Navbar實作了navbar,至于app-main,根據各項路由的component參數可知,一般都放在views/目錄下

繼續閱讀