首頁 >web前端 >js教程 >如何實作載入權限管理模組(詳細教學)

如何實作載入權限管理模組(詳細教學)

亚连
亚连原創
2018-06-11 17:36:111762瀏覽

這篇文章給大家詳細講解如何在權限管理模組中動態的載入VUE元件的過程,有這方面需求的朋友跟著學習下吧。

本文我們主要來聊聊登入以及元件的動態載入。

登入狀態保存

當使用者登入成功之後,需要將目前使用者的登入資訊儲存在本機,方便後面使用。具體實現如下:

登入成功儲存資料

在登入作業執行成功之後,透過commit作業將資料提交到store中,核心程式碼如下:

this.postRequest('/login', {
  username: this.loginForm.username,
  password: this.loginForm.password
}).then(resp=> {
  if (resp && resp.status == 200) {
  var data = resp.data;
  _this.$store.commit('login', data.msg);
  var path = _this.$route.query.redirect;
  _this.$router.replace({path: path == '/' || path == undefined ? '/home' : path});
  }
});

store

store的核心程式碼如下:

export default new Vuex.Store({
 state: {
  user: {
   name: window.localStorage.getItem('user' || '[]') == null ? '未登录' : JSON.parse(window.localStorage.getItem('user' || '[]')).name,
   userface: window.localStorage.getItem('user' || '[]') == null ? '' : JSON.parse(window.localStorage.getItem('user' || '[]')).userface
  }
 },
 mutations: {
  login(state, user){
   state.user = user;
   window.localStorage.setItem('user', JSON.stringify(user));
  },
  logout(state){
   window.localStorage.removeItem('user');
  }
 }
});

為了減少麻煩,使用者登入成功後的資料將保存在localStorage中(防止使用者按F5刷新之後資料遺失),以字串的形式存入,取的時候再轉為json。當使用者登出登陸時,將localStorage中的資料清除。

元件動態載入

在權限管理模組中,這算是前端的核心了。

核心思路

用戶在登入成功之後,進入home主頁之前,向服務端發送請求,要求獲取當前的菜單信息和組件信息,服務端根據目前使用者所具備的角色,以及角色所對應的資源,傳回一個json字串,格式如下:

[
  {
    "id": 2,
    "path": "/home",
    "component": "Home",
    "name": "员工资料",
    "iconCls": "fa fa-user-circle-o",
    "children": [
      {
        "id": null,
        "path": "/emp/basic",
        "component": "EmpBasic",
        "name": "基本资料",
        "iconCls": null,
        "children": [],
        "meta": {
          "keepAlive": false,
          "requireAuth": true
        }
      },
      {
        "id": null,
        "path": "/emp/adv",
        "component": "EmpAdv",
        "name": "高级资料",
        "iconCls": null,
        "children": [],
        "meta": {
          "keepAlive": false,
          "requireAuth": true
        }
      }
    ],
    "meta": {
      "keepAlive": false,
      "requireAuth": true
    }
  }
]

前端在拿到這個字串之後,做兩件事:1.將json動態加入到目前路由中;2.將資料儲存到store中,然後各頁根據store中的資料來渲染選單。

核心想法並不難,下面我們來看看實作步驟。

資料請求時機

這個很重要。

可能會有小夥伴說這有何難,登入成功之後請求不就可以了嗎?是的,登入成功之後,請求選單資源是可以的,請求到之後,我們將之保存在store中,以便下一次使用,但是這樣又會有另外一個問題,假如用戶登入成功之後,點擊某一個子頁面,進入子頁面中,然後按了一下F5進行刷新,這個時候就GG了,因為F5刷新之後store中的資料就沒了,而我們又只在登入成功的時候請求了一次選單資源,要要解決這個問題,有兩種想法:1.將選單資源不要儲存到store中,而是儲存到localStorage中,這樣即使F5刷新之後資料還在;2.直接在每一個頁面的mounted方法中,都去載入一次選單資源。

由於選單資源是非常敏感的,因此最好不要不要將其保存到本地,故捨棄方案1,但是方案2的工作量有點大,因此我採取辦法將之簡化,採取的辦法就是使用路由中的導航守衛。

路由導航守衛

我的具體實作是這樣的,首先在store中建立一個routes數組,這是一個空數組,然後開啟路由全域守衛,如下:

router.beforeEach((to, from, next)=> {
  if (to.name == 'Login') {
   next();
   return;
  }
  var name = store.state.user.name;
  if (name == '未登录') {
   if (to.meta.requireAuth || to.name == null) {
    next({path: '/', query: {redirect: to.path}})
   } else {
    next();
   }
  } else {
   initMenu(router, store);
   next();
  }
 }
)

這裡的程式碼很短,我來做一個簡單的解釋:

#1.如果要去的頁面是登入頁面,這個沒啥好說的,直接過。

2.如果不是登入頁面的話,我先從store中取得目前的登入狀態,如果未登錄,則透過路由中meta屬性的requireAuth屬性判斷要去的頁面是否需要登錄,如果需要登入,則跳回登錄頁面,同時將要去的頁面的path作為參數傳給登錄頁面,以便在登錄成功之後跳到目標頁面,如果不需要登錄,則直接過(事實上,本項目中只有Login頁面不需要登入);如果已經登入了,則先初始化選單,再跳轉。

初始化選單的操作如下:

export const initMenu = (router, store)=> {
 if (store.state.routes.length > 0) {
  return;
 }
 getRequest("/config/sysmenu").then(resp=> {
  if (resp && resp.status == 200) {
   var fmtRoutes = formatRoutes(resp.data);
   router.addRoutes(fmtRoutes);
   store.commit('initMenu', fmtRoutes);
  }
 })
}
export const formatRoutes = (routes)=> {
 let fmRoutes = [];
 routes.forEach(router=> {
  let {
   path,
   component,
   name,
   meta,
   iconCls,
   children
  } = router;
  if (children && children instanceof Array) {
   children = formatRoutes(children);
  }
  let fmRouter = {
   path: path,
   component(resolve){
    if (component.startsWith("Home")) {
     require(['../components/' + component + '.vue'], resolve)
    } else if (component.startsWith("Emp")) {
     require(['../components/emp/' + component + '.vue'], resolve)
    } else if (component.startsWith("Per")) {
     require(['../components/personnel/' + component + '.vue'], resolve)
    } else if (component.startsWith("Sal")) {
     require(['../components/salary/' + component + '.vue'], resolve)
    } else if (component.startsWith("Sta")) {
     require(['../components/statistics/' + component + '.vue'], resolve)
    } else if (component.startsWith("Sys")) {
     require(['../components/system/' + component + '.vue'], resolve)
    }
   },
   name: name,
   iconCls: iconCls,
   meta: meta,
   children: children
  };
  fmRoutes.push(fmRouter);
 })
 return fmRoutes;
}

在初始化選單中,首先判斷store中的資料是否存在,如果存在,說明這次跳轉是正常的跳轉,而不是用戶按F5或直接在網址列輸入某個位址進入的。否則就去加載選單。拿到選單之後,先透過formatRoutes方法將伺服器傳回的json轉為router需要的格式,這裡主要是轉component,因為服務端回傳的component是一個字串,而router中需要的卻是個元件,因此我們在formatRoutes方法中動態的載入所需的元件即可。資料格式準備成功之後,一方面將資料存到store中,另一方面利用路由中的addRoutes方法將動態加入路由中。

選單渲染

最後,在Home頁中,從store中取得選單json,渲染成選單即可,相關程式碼可以在Home.vue中查看,不贅述。

OK,如此之後,不同使用者登入成功之後就可以看到不同的選單了。

上面是我整理給大家的,希望今後對大家有幫助。

相關文章:

在vue.js中如何取得select中的value值(詳細教學)

在Vue2.0系列中如何使用濾鏡?

在vue專案中透過tween方法如何實現返回頂部

使用vue如何判斷input輸入內容全是空格?

使用js判斷輸入框不能為空格或null值該如何實作?

以上是如何實作載入權限管理模組(詳細教學)的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn