打造vuecli3+element後臺管理系統(三)優化路由和vuex倉庫,給router和store分模塊

咱們在作後臺系統的時候,常常會有比較多的功能頁面,每一個頁面或多或少都會有須要存儲在vuex中的數據,通常狀況下咱們會在state下定義不一樣的object,可是當功能一多,所有字段和action、mutations都定義在一個文件裏,不免會使文件變得很難維護。所有頁面的路由都定義在一個路由文件裏也會使文件代碼變得比較多,後期維護麻煩。因此咱們應該將倉庫和路由「模塊化」,不一樣功能定義不一樣的模塊文件,最後統一在index文件引入。javascript

1、路由分模塊

1.1 建立router文件夾,存放路由定義文件

  • 建立modules文件夾,主要存放功能頁面路由定義文件
  • 建立index.js文件,定義路由
1.1-1 @/router/index.js

router/index.js主要功能是:vue

  1. 定義常規路由,即那些不須要權限就可訪問的頁面,好比說登陸註冊、後臺主頁、404頁面等。
  2. 引入須要根據權限加載的路由模塊
  3. 定義建立路由、重置路由方法
// index.js
import Vue from 'vue'
import Router from 'vue-router'

Vue.use(Router)
// 定義常規路由
export const constantRoutes = [
  {
    path: '/redirect',
    component: () => import('@/layout'),
    hidden: true,
    children: [
      {
        path: '/redirect/:path*',
        component: resolve => void require(['@/views/redirect/index'], resolve)
      }
    ]
  },
  {
    path: '/',
    redirect: '/login'
  },
  {
    path: '/login',
    name: 'Login',
    component: resolve => void require(['@/views/login/index'], resolve),
    hidden: true
  },
  {
    path: '/register',
    name: 'Register',
    component: resolve => void require(['@/views/login/register'], resolve),
    hidden: true
  },
  {
    path: '/resetPsw',
    name: 'ResetPsw',
    component: resolve => void require(['@/views/login/resetPsw'], resolve),
    hidden: true
  },

  {
    path: '/404',
    component: () => import('@/views/404'),
    hidden: true
  }
]

/** 權限路由 * 是動態的路由、須要根據權限加載的路由 */
const modulesFiles = require.context('./modules', true, /\.js$/)
const routesModules = []
// 自動引入modules目錄下的全部模塊
modulesFiles.keys().reduce((modules, modulePath) => {
  const value = modulesFiles(modulePath)
  routesModules.push(value.default)
}, {})
export const asyncRoutes = routesModules

/** 404路由 * 最終沒法匹配到相應路由,重定向到404 * 異步加載路由時,在生成完異步路由準備掛載時,須要將重定向404的匹配規則定義在最後面,不然刷新會出錯。 */
export const notFoundRoutes = [
  {
    path: '*',
    redirect: '/404',
    hidden: true,
    meta: {
      title: '404'
    }
  }
]

// 定義實例化路由的方法
const createRouter = () => new Router({
  // mode: 'history', // require service support
  scrollBehavior: () => ({ y: 0 }),
  routes: constantRoutes // 掛載常規路由
})
// 實例化路由
const router = createRouter()

// 定義實重置路由的方法
export function resetRouter() {
  const newRouter = createRouter()
  router.matcher = newRouter.matcher // reset router
}

export default router
複製代碼

2、vuex倉庫分模塊

和router模塊同樣,咱也須要給store模塊建立一個文件夾,在裏頭存放定義文件java

2.1 建立store文件夾,存放vuex定義文件

  • 建立modules文件夾,主要存放各模塊下的倉庫定義文件
  • 建立index.js文件,初始化vuex實例
  • 使用vuex持久化插件vuex-persistedstate,讓你的數據能夠實現刷新也不丟失噢~
2.1-1 @/store/index.js

該文件聲明瞭vuex實例,同時批量引入modules下的store文件,也聲明瞭vuex-persistedstate插件實例。git

關於persistedState的初始化,注意vuex中的參數不是所有都要持久化,你能夠根據業務邏輯自行定義須要持久化的參數 github

import Vue from 'vue'
import Vuex from 'vuex'
import getters from './getters'
import createPersistedState from 'vuex-persistedstate'

Vue.use(Vuex)

// (建立了)一個包含了modules文件夾(包含子目錄)下面的,全部文件名以 `.js` 結尾的、能被 require 請求到的文件的上下文。
const modulesFiles = require.context('./modules', true, /\.js$/)
// keys() 方法用於從modules建立一個包含modules裏鍵值的可迭代對象。
const modules = modulesFiles.keys().reduce((modules, modulePath) => {
  // 模塊名,取文件名
  const moduleName = modulePath.replace(/^\.\/(.*)\.\w+$/, '$1')
  // 獲取鍵名爲modulePath的文件內容
  const value = modulesFiles(modulePath)
  // 將文件中的默認導出模塊 賦值給迭代對象modules
  modules[moduleName] = value.default
  // 返回迭代對象modules
  return modules
  // 默認值是空對象{}
}, {})

// 建立倉庫實例
const store = new Vuex.Store({
  modules,
  getters,
  // 使用持久化插件
  plugins: [
    // 存儲vuex狀態,使之刷新不丟失
    createPersistedState({
      // 這裏我用的是localStorage,你也能夠改爲sessionStorage,cookie也行不過我沒研究嘻嘻嘻
      storage: window.localStorage,
      reducer(val) {
        return {
          // 將要存儲的state中的值放在這裏
          user: {
            name: val.user.name
          }
        }
      }
    })
  ]
})

export default store

複製代碼

那咱們就來看看咋使用,咱們能夠寫個userjs來試試,裏頭定義登陸登出的action,由於登陸登出可能不止一個地方會運用到,並且登陸登出可能會涉及到state裏頭好幾個狀態值的改變,因此我就把登陸登出的邏輯寫在action裏頭,這樣分發的時候也能夠改變狀態值:vue-router

2.1-2 modules目錄下新建user.js,用來存放用戶信息,定義登錄、登出的action
import API from '@/assets/http/apiUrl'
import Request from '@/assets/http'

const user = {
  state: {
    token: '',
    name: ''
  },
  mutations: {
    SET_TOKEN: (state, data) => {
      // 先初步定義token和username這兩個值
      state.token = data
      localStorage.setItem('ADMIN_TOKEN', data)
    },
    SET_NAME: (state, data) => {
      state.name = data
    }
  },
  actions: {
    // 登錄
    Login({ commit }, params) {
      return new Promise((resolve, reject) => {
        Request.httpRequest({
          method: 'post',
          url: API.Login,
          params: params,
          success: data => {
            commit('SET_TOKEN', data.token)
            resolve(data)
          },
          error: err => {
            reject(err)
          }
        })
      })
    },

    // 短信登陸,這裏爲了方便我就直接複用登陸的action了,正式項目中確定要調用另外的接口
    LoginByVin({ dispatch, commit }, params) {
      return dispatch('Login', params)
    },

    // 重置token和state值
    ResetToken({ commit }) {
      return new Promise(resolve => {
        commit('SET_TOKEN', '')
        commit('SEI_NAME', '')
        localStorage.removeItem('ADMIN_TOKEN')
        resolve()
      })
    },

    // 登出
    LogOut({ dispatch, commit }) {
      return dispatch('ResetToken')
    }
  }
}

export default user

複製代碼

新建以後不須要在index那裏引入哦,由於咱們已經寫了批量引入的邏輯啦~是否是很方便呢vuex

而後就是使用了,關於Login,在登錄頁面只須要分發action就行:api

params = {
    'username': this.loginForm.user,
    'password': this.loginForm.password
}
this.$store.dispatch('Login', params).then(() => {
    this.loading = false
    this.$router.push({ path: this.redirect || '/home' })
}).catch(() => {
    this.loading = false
})
複製代碼

具體代碼邏輯能夠下載項目來看一下下bash

相關文章
相關標籤/搜索