vue element從0到1之(一)從main.js到login.vue

學習vue elementui最大的挑戰就是執行邏輯的理清,vue中存在很多隱式的調用,這讓我們的思維非常的混亂和跳躍,像router的捕獲以及到底什麼時候去調用了一個vuex的方法,都非常的隱晦,造成我們不能順着一條線,順藤摸瓜式的理解整個事物,這也是我們拿到一個vue的項目一頭霧水的根源。本文抽絲剝繭,力圖將vue的執行流程做一個梳理。能讓我們對整個執行流程有一個全面清晰的認識:

我這裏以el-admin的前端代碼爲例來講解,代碼下載請訪問https://gitee.com/elunez/eladmin-web

所有的程序都有一個開始,這就像是開機一樣,vue的開始就是main.js

1.main.js

new Vue({
  el: '#app',
  router,
  store,
  render: h => h(App)
})

可以看到,這裏加載了router路由和store(數據)

但是這個僅僅是程序的開始,我們作爲一個使用者,首先去理解這個程序的執行卻是從登錄開始的。我們想知道的是登錄頁面發生了什麼。

當我們訪問http://localhost:8013/#/login的時候到底是誰負責帶路找到頁面呢?答案是路由

2.路由,router/index.js

router下面有兩個文件,一個是index.js 一個是router.js

由於我們要對所有的請求進行安全檢查,所以我們需要在請求到達頁面之前,設置一個過濾器,這個過濾的目的是,比如,當用戶沒有登陸的時候直接重定向到登錄頁,當用戶登錄的時候去拉取菜單。index.js裏面定義了攔截器

router.beforeEach((to, from, next) => {
  if (to.meta.title) {
    document.title = to.meta.title + ' - ' + Config.title
  }
  NProgress.start()
  if (getToken()) {
    // 已登錄且要跳轉的頁面是登錄頁
    if (to.path === '/login') {
      next({path: '/'})
      NProgress.done()
    } else {
      if (store.getters.roles.length === 0) { // 判斷當前用戶是否已拉取完user_info信息
        store.dispatch('GetInfo').then(res => { // 拉取user_info
          console.log("GetInfo");
          // 動態路由,拉取菜單
          loadMenus(next, to)
        }).catch((err) => {
          console.log(err)
          store.dispatch('LogOut').then(() => {
            location.reload() // 爲了重新實例化vue-router對象 避免bug
          })
        })
        // 登錄時未拉取 菜單,在此處拉取
      } else if (store.getters.loadMenus) {
        // 修改成false,防止死循環
        store.dispatch('updateLoadMenus').then(res => {
        })
        loadMenus(next, to)
      } else {
        next()
      }
    }
  } else {
    /* has no token*/
    if (whiteList.indexOf(to.path) !== -1) { // 在免登錄白名單,直接進入
      next()
    } else {
      next(`/login?redirect=${to.path}`) // 否則全部重定向到登錄頁
      NProgress.done()
    }
  }
})
這個就是一個攔截器,在路由到真正的頁面之前,進行數據準備和登錄狀態驗證。

可以看到當我們未登錄訪問任意頁面的時候,index.js沒有獲取到token於是直接重定向到了login這個url

而login具體的指向的頁面在route.js裏面定義

3.route.js

import Vue from 'vue'
import Router from 'vue-router'
import Layout from '../layout/index'

Vue.use(Router)

export const constantRouterMap = [
  {
    path: '/login',
    meta: {title: '登錄', noCache: true},
    component: (resolve) => require(['@/views/login'], resolve),
    hidden: true
  },
  {
    path: '/404',
    component: (resolve) => require(['@/views/features/404'], resolve),
    hidden: true
  },
  {
    path: '/401',
    component: (resolve) => require(['@/views/features/401'], resolve),
    hidden: true
  },
  {
    path: '/redirect',
    component: Layout,
    hidden: true,
    children: [
      {
        path: '/redirect/:path*',
        component: (resolve) => require(['@/views/features/redirect'], resolve)
      }
    ]
  },
  {
    path: '/',
    component: Layout,
    redirect: '/dashboard',
    children: [
      {
        path: 'dashboard',
        component: (resolve) => require(['@/views/home'], resolve),
        name: 'Dashboard',
        meta: {title: '首頁', icon: 'index', affix: true, noCache: true}
      }
    ]
  },
  {
    path: '/user',
    component: Layout,
    hidden: true,
    redirect: 'noredirect',
    children: [
      {
        path: 'center',
        component: (resolve) => require(['@/views/system/user/center'], resolve),
        name: '個人中心',
        meta: {title: '個人中心'}
      }
    ]
  }
]

export default new Router({
  // mode: 'history',
  base: '/',
  scrollBehavior: () => ({y: 0}),
  routes: constantRouterMap
})

可以看到,最終指向的views/login這個組件

4.login.vue

至此,我們看到了迷宮的入口!

https://el-admin.xin/login?redirect=%2Fsystem%2Frole

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章