動態載入許可權管理模組中的Vue組件,許可權管理vue

來源:互聯網
上載者:User

動態載入許可權管理模組中的Vue組件,許可權管理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,如此之後,不同使用者登入成功之後就可以看到不同的菜單了。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.