vue管理後臺

手摸手,帶你用vue擼後臺 系列四(vueAdmin 一個極簡的後臺基礎模板)
基於這篇文章的學習,開始動手寫了一個簡易的vue管理後臺。vue

技術棧

  • vue-axios
  • vue-cli
  • vue-router
  • element-ui
  • 第三方插件

目前實現功能

  • 登陸/退出
  • 麪包屑導航
  • 全局樹形導航

主要頁面以下

  • 登陸

clipboard.png

  • 主頁 (頁面的結構基本和主頁相同。左側導航欄,右側上方面包屑導航和用戶頭像,右側下方大塊空白區域對應的是各路由)

clipboard.png

  • 項目結構

clipboard.png

views:各業務組件
components:公共組件(麪包屑,導航開關等等)
api: 請求的js文件
icons: svg和相關配置文件(此項目的圖標是使用svg-sprite-loader來實現的, 以前寫過的相關文章連接
permission.js 檢查權限
其餘地方與別的項目結構一致,我就再也不贅述了。ios

接下來我會以 實現頁面的結構、麪包屑導航、左側樹形導航、頁面跳轉這四個基礎模塊去講解。由於篇幅有限,在這篇文章只放功能相關的部分代碼,github源碼連接在文章最後。git

1.實現頁面的結構。

(由於除了login等特殊頁面外,其餘的結構都是一致的。因此能夠用Layout組件來承載頁面的結構)
@/views/Layout/的目錄結構以下github

clipboard.png

對應到Layout的各個區域以下圖。ajax

clipboard.png

  • @/router/index.js 路由器。

當點擊切換路由時,sidebar和navbar不會改變,只有app-main組件的內容會改變。
實現思路:左側導航欄的路由的component爲Layout,再經過router的redirect屬性控制顯示app-main區域的路由。部分代碼以下vue-router

@/Layout/Layout.vuevue-cli

<template>
    <div class="app-wrapper" :class="classObj">
        <!--導航 -->
        <sidebar/>
        <!--麪包屑-->
        <div class="main-container">
            <!-- 頭部導航 -->
            <navbar/>
            <!-- 二級路由 -->
            <app-main/>
        </div>
    </div>
</template>
<script>
import Sidebar from './components/Sidebar'
import Navbar from './components/navbar'
import AppMain from './components/AppMain'
</script>

@/Layou/components/AppMain.vueelement-ui

<template>
    <section class="app-main">
        <transition name="fade-transform" mode="out-in">
            <!-- 在這裏映射不一樣的路由到Layout中的app-main -->
            <router-view/>
        </transition>
    </section>
</template>

2.左側導航

左側的導航是經過element-ui的 el-menu組件和循環路由表來實現的。具體效果以下圖
圖片描述axios

若是沒有子路由,點擊直接跳轉。有則出現下拉彈框。segmentfault

3.麪包屑導航

使用element-ui裏的el-breadcrumb組件,循環this.$router.matched數組渲染el-breadcrumb。
this.$router.matched數組包含當前路由的全部嵌套路徑片斷的路由記錄(包括它的子路由)。
部分代碼以下@/components/breadcrumb/index

<template>
    <el-breadcrumb class="app-breadcrumd" separator="/">
        <transition-group name="breadcrumb">
            <el-breadcrumb-item v-for="(item, index) in levelList" v-if="item.meta.title" :key="item.path">
                <!--當前路由,點擊不作跳轉 -->
                <span v-if="item.redirect==='noredirect'||index==levelList.length-1" class="no-redirect">{{ item.meta.title }}</span>
                <a v-else @click.prevent="handleLink(item)">{{item.meta.title}}</a>
            </el-breadcrumb-item>
        </transition-group>
    </el-breadcrumb>
</template>

4.登陸

該項目的處理邏輯爲:
a.經過帳號密碼請求登陸api獲取token
b.將token保存到cookie和store中
c.經過判斷token是否存在和導航守衛來控制路由
下面我將以上abc三個步驟分開來寫


a:表單驗證和發送請求

@/views/login/index 登陸頁,表單使用elementui的el-form。

<!-- :rules 表單校驗規則的對象 {username:[],password:[]}-->
<!-- loginForm 整個表單須要提交的字段 {username:'',password:''} -->
<el-form :rules="loginRules" :model="loginForm">
    <!-- username是必填項 prop對應要驗證的字段username -->
    <el-form-item prop="username">
       <el-input
            v-model="loginForm.username"
            name="username" type="text"
            auto-complete="on"
            placeholder="username" />
    </el-form-item>
    <!-- 密碼 -->
    <el-form-item prop="password">
        <el-input
            v-model="loginForm.username"
            type="password"
            name="password"
            auto-complete="on" />
    </el-form-item>
</el-form>
data() {
   //username的校驗規則
   const validateUsername = (rule, value, callback) => {
     // rule 對應的爲loginRules.username的值
     if (!isvalidUsername(value)) {
       callback(new Error('請輸入正確的用戶名'))
     } else {
       callback()
     }
   }
   // password的校驗規則
   const validatePass = (rule, value, callback) => {
     if (value.length < 5) {
       callback(new Error('密碼不能小於5位'))
     } else {
       callback()
     }
   }
   return {
       // 表單校驗規則
       loginRules: {
           //required 是否必須 trigger 觸發條件 validator 該字段的校驗規則
           username: [{required: true, trigger: 'blur', validator: validateUsername}],
           password: [{required: true, trigger: 'blur', validator: validatePass}]
         },
       // 表單提交對象
       loginForm: {
          username:
       }
   }
}

發送請求
(由於沒有後臺的相關api,因此該項目的登陸、獲取用戶信息都是在 https://easy-mock.com/mock/59...
該登陸接口下的帳號是 admin、editor。密碼不能小於5位)

在開發環境下配置這個請求接口的域名
config/dev.env.js

module.exports = merge(prodEnv, {
  NODE_ENV: '"development"',
  BASE_API: '"https://easy-mock.com/mock/5950a2419adc231f356a6636/vue-admin"' //直接經過process.env.BASE_API 來獲取
})

@/utils/request 封裝ajax請求相關
@/api/login 封裝登陸,獲取用戶信息相關的接口


b
請求成功獲取token後保存到cookie和store中。這一步再也不仔細,詳細代碼在如下幾個文件
處理token @/utils/auth
登陸 @/api/login
封裝axios @/utils/request


C 經過判斷token是否存在和導航守衛來控制路由
@/permission.js
處理邏輯:

(1)token存在,根據beforeRouter的to屬性判斷.
    前往login,則經過next({path:'/'})改變to.path,由於不須要再登陸。
    前往其餘頁面,先判斷store裏的roles數組是否爲空(roles用來控制權限),若是爲空則獲取用戶信息,再next()或者直接next()
(2)token不存在,判斷to.path是否存在白名單路由數組
    存在,直接next()
    不存在,前往login將to.path做爲參數攜帶在url中,/login?redirect=${to.path},
    登陸成功後再跳轉到to.path

項目源碼

若是喜歡請給個star吧!
https://github.com/lazyChan29...

相關文章
相關標籤/搜索