最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

基于Vue實現(xiàn)后臺系統(tǒng)權(quán)限控制的示例代碼

 更新時間:2017年08月29日 11:17:40   作者:雅X共賞  
本篇文章主要介紹了基于Vue實現(xiàn)后臺系統(tǒng)權(quán)限控制的示例代碼,具有一定的參考價值,感興趣的小伙伴們可以參考一下

用Vue/React這類雙向綁定框架做后臺系統(tǒng)再適合不過,后臺系統(tǒng)相比普通前端項目除了數(shù)據(jù)交互更頻繁以外,還有一個特別的需求就是對用戶的權(quán)限控制,那么如何在一個Vue應(yīng)用中實現(xiàn)權(quán)限控制呢?下面是我的一點經(jīng)驗。

權(quán)限控制是什么

在權(quán)限的世界里服務(wù)端提供的一切都是資源,資源可以由請求方法+請求地址來描述,權(quán)限是對特定資源的訪問許可,所謂權(quán)限控制,也就是確保用戶只能訪問到被分配的資源。具體的說,前端對資源的訪問通常是由界面上的按鈕發(fā)起,比如刪除某條數(shù)據(jù);或由用戶進(jìn)入某一個頁面發(fā)起,比如獲取某個列表數(shù)據(jù)。這兩種形式覆蓋了資源請求的大部分場景,因此權(quán)限控制也可以被籠統(tǒng)的分成菜單權(quán)限控制和按鈕權(quán)限控制。

Vue菜單權(quán)限控制

菜單是對路由的直接體現(xiàn),菜單控制實際上就是路由控制。實現(xiàn)路由控制一個簡單的方式是,在路由的before鉤子里校驗當(dāng)前即將跳轉(zhuǎn)的路由地址是否有權(quán)訪問,根據(jù)校驗結(jié)果決定路由是否放行,偽碼:

router.beforeEach((to, from, next) => {
  //權(quán)限校驗
  let pass = valid(to);
  if(!pass){
    return console.log('無權(quán)訪問');
  }
  next();
});

這種實現(xiàn)方式既簡單又直觀,用于簡單的系統(tǒng)非常合適,但這么做本質(zhì)上是將所有路由全部注冊了,直接帶來的缺點有兩個:一、如果路由組件不是按需加載的話,應(yīng)用將加載大量冗余代碼;二、每次跳轉(zhuǎn)都要遍歷一次完整路由是對計算能力的浪費,對于路由總數(shù)較大的應(yīng)用很不可取。

理想的實現(xiàn)方式是本地保存完整路由,但并不立即初始化Vue應(yīng)用,待用戶登錄拿到權(quán)限后,用菜單權(quán)限篩選出可用路由,再用可用路由初始化Vue應(yīng)用。也就是說,要將登錄頁獨立出去做成一個單獨的頁面,登錄后將用戶數(shù)據(jù)保存在本地,再通過url跳轉(zhuǎn)到Vue應(yīng)用所在頁面,Vue應(yīng)用啟動前通過本地用戶數(shù)據(jù)完成路由篩選,然后初始化Vue應(yīng)用,偽碼如下:

//main.js
let user = sessionStorage.getItem('user');
if (user) {
  user = JSON.parse(user);
  //篩選得到實際路由
  let fullPath = require('fullPath.js');
  let routes = filter(fullPath, user.menus);
  //創(chuàng)建路由對象
  let router = new Router({routes});
  //生成Vue實例
  new Vue({
    el: '#app',
    router,
    render: h => h(App)
  });
}else{
  location.href = '/login/';
}

這樣我們就根據(jù)用戶權(quán)限生成了一套”定制”路由,這時我們還希望能直接用路由生成導(dǎo)航菜單,常規(guī)的路由數(shù)據(jù)可能無法滿足菜單組件的需求,所以我們可以事先在路由的meta數(shù)據(jù)里維護上菜單數(shù)據(jù),比如菜單名稱菜單圖標(biāo)等,只要在模板中通過$router.options就可以訪問到當(dāng)前路由數(shù)據(jù),如果使用element-ui的菜單組件實現(xiàn),代碼大致是這樣的:

<el-menu router>
  <el-menu-item v-for="(route, index) in $router.options.routes[2].children"
  :route="route"
  :index="route.name">
    <i class="ion" v-html="route.icon"></i>{{route.name}}
  </el-menu-item>
</el-menu>

當(dāng)然這樣只能循環(huán)出一級菜單,如果還有二級路由需要對應(yīng)二級菜單的話,就得判斷并循環(huán)children節(jié)點,比較簡單就不放更多代碼了,菜單權(quán)限控制到這里就完成了。

Vue按鈕權(quán)限控制

按鈕權(quán)限控制與菜單權(quán)限控制的實現(xiàn)思路類似,也是根據(jù)用戶權(quán)限判斷各個按鈕的顯示與否,方式無非是v-if或自定義指令,而且只要將v-if背后的權(quán)限校驗邏輯抽象成方法,無論是代碼量還是使用形式上都跟自定義指令幾乎一樣,但v-if的特點是它會響應(yīng)數(shù)據(jù)變化,因此隨著應(yīng)用的運行會頻繁觸發(fā)權(quán)限校驗,而權(quán)限在應(yīng)用的整個生命周期內(nèi)其實只需校驗一次,為了避免無謂的程序執(zhí)行,這里可以用自定義指令來實現(xiàn),偽碼:

Vue.directive('has', {
 bind: function (el, binding) {
  if(!has(binding.value)){
    el.parentNode.removeChild(el);
  }
 }
});

//用法:
<btn v-has='get,/sources'>按鈕</btn>

注意在指令bind回調(diào)里有一個has()方法,這就是權(quán)限校驗方法,我們同時將這個方法全局混合到Vue對象中,使應(yīng)用里的每個組件都可以訪問到這個方法,便于為界面上的v-if提供支持,例如:

<div v-if="has('get,/sources') && something">
  一個需要同時具備'get,/sources'權(quán)限和somthing為真值才顯示的div
</div>

這樣一來凡是需要依據(jù)權(quán)限實現(xiàn)的按鈕顯隱控制和界面變化都可以很方便的實現(xiàn)。

但按鈕權(quán)限控制真正麻煩的地方不在于如何實現(xiàn),而在于高昂的維護成本。我們假設(shè)按鈕Btn綁定了點擊回調(diào)Fn,回調(diào)Fn里發(fā)起了請求Req,請求Req需要某個資源的訪問權(quán)限,最終你要根據(jù)用戶是否擁有Req的權(quán)限,決定Btn是否顯示,而Req跟Btn之間并沒有直接關(guān)聯(lián),所以我們就要人肉維護他們的關(guān)系,一個復(fù)雜項目里的按鈕有個幾十上百都很正常,隨著業(yè)務(wù)的變更去維護這么多按鈕的權(quán)限,想想都頭疼。

有一個方法可以繞開這個爛攤子,那就是前端放棄對視圖層的控制,退到請求層面,在請求發(fā)起前集中攔截,這時可以直接根據(jù)請求方法和請求地址來校驗權(quán)限,除了實現(xiàn)一個攔截器之外不需要額外的代碼,可以說非常優(yōu)雅了。以axios為例,攔截器大概長這樣:

axios.interceptors.request.use(function (config) {
 if(!has(config)){
 //驗證不通過
  return Promise.reject({
   message: `no permission`
  });
 }
 return config;
});

但如果僅僅這樣做權(quán)限控制,界面上將顯示出所有的按鈕,用戶看到的按鈕卻不一定可以點擊,這種體驗我認(rèn)為只能停留在理論層面,根本無法應(yīng)用到實際產(chǎn)品中。請求控制可以作為整個控制體系的第二道防線,或某些特殊情況下的輔助手段,最終還是要回到按鈕控制的思路上來。

那么怎樣能盡可能方便的采集到每個按鈕所需的權(quán)限呢?按鈕和權(quán)限之間隔著兩層?xùn)|西,第一層是click回調(diào),第二層是回調(diào)里的AJAX請求,不想人肉維護就得想辦法突破這兩層隔閡,讓按鈕和權(quán)限產(chǎn)生聯(lián)系,按鈕必然要綁定click事件,最理想的采集方式是在綁定事件的同時得到所需權(quán)限,讓一切自然而然的發(fā)生,比如這樣,

<btn v-do="Fn">按鈕</btn>

如果Fn能以某種形式采集到內(nèi)部的AJAX請求參數(shù),并轉(zhuǎn)化成權(quán)限信息傳遞出來就完美了,然而我沒找到可行的方法,并且這種形式在應(yīng)用上也存在缺陷,因為不一定每個操作按鈕都會發(fā)起AJAX請求,比如編輯按鈕本身并不會觸發(fā)請求,真正觸發(fā)請求的是另一個保存按鈕,所以這個思路只是看起來很美。

那么退而求其次的做法是讓按鈕和請求聯(lián)系起來,比如說按鈕涉及一個名稱為A的請求,那么我希望權(quán)限指令可以這樣寫,

<btn v-has="A" @click="Fn">按鈕</btn>

比完美形態(tài)是差了不少,但起碼不需要手動維護到'get,/resources'這個級別了,這里對A的實現(xiàn)可以有多種形式,比如A可以是一個包含兩個屬性的對象:

const A = {
 p: ['put,/menu/**'],
 r: params => {
  return axios.put(`/menu/${params.id}`, params)
 }
};

//用作權(quán)限:
<btn v-has="[A]" @click="Fn">按鈕</btn>
//用作請求:
function Fn(){
  A.r().then((res) => {})
}

通常我們會將項目里所有的api放在一個api模塊里集中管理,在寫api時順便就把權(quán)限給維護了,換來的是在組件界面里可以直接用請求名稱來描述權(quán)限,而不需要來回奔波于界面和api模塊之間,一定程度上實現(xiàn)了關(guān)注點分離,而且has指令還可以進(jìn)一步做優(yōu)化,例如參數(shù)只需要接收A,指令內(nèi)部根據(jù)約定自動訪問A.p來獲取權(quán)限,還可以接收數(shù)組,允許多個權(quán)限聯(lián)合校驗。

后記

好了,這就是我對前端權(quán)限控制的一些實踐和思考,如有不當(dāng)歡迎指正。

最后吐槽一下Element-UI,真心難看。

感謝閱讀,希望能幫助到大家,謝謝大家對本站的支持!

相關(guān)文章

  • vue實現(xiàn)圖片滾動的示例代碼(類似走馬燈效果)

    vue實現(xiàn)圖片滾動的示例代碼(類似走馬燈效果)

    下面小編就為大家分享一篇vue實現(xiàn)圖片滾動的示例代碼(類似走馬燈效果),具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-03-03
  • 基于Vue實現(xiàn)拖拽功能

    基于Vue實現(xiàn)拖拽功能

    這篇文章主要為大家詳細(xì)介紹了Vue實現(xiàn)拖拽功能,拖動方塊進(jìn)行移動,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-04-04
  • Vue項目中對index.html中BASE_URL的配置方式

    Vue項目中對index.html中BASE_URL的配置方式

    這篇文章主要介紹了Vue項目中對index.html中BASE_URL的配置方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-06-06
  • Vue2?中自定義圖片懶加載指令?v-lazy實例詳解

    Vue2?中自定義圖片懶加載指令?v-lazy實例詳解

    這篇文章主要為大家介紹了Vue2?中自定義圖片懶加載指令?v-lazy實例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-09-09
  • vue3中el-table實現(xiàn)表格合計行的示例代碼

    vue3中el-table實現(xiàn)表格合計行的示例代碼

    這篇文章主要介紹了vue3中el-table實現(xiàn)表格合計行,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友參考下吧
    2024-01-01
  • 解決Vue.js 2.0 有時雙向綁定img src屬性失敗的問題

    解決Vue.js 2.0 有時雙向綁定img src屬性失敗的問題

    下面小編就為大家分享一篇解決Vue.js 2.0 有時雙向綁定img src屬性失敗的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-03-03
  • vue使用window.open()跳轉(zhuǎn)頁面的代碼案例

    vue使用window.open()跳轉(zhuǎn)頁面的代碼案例

    這篇文章主要介紹了vue中對window.openner的使用,vue使用window.open()跳轉(zhuǎn)頁面的代碼案例,本文通過實例代碼給大家詳細(xì)講解,需要的朋友可以參考下
    2022-11-11
  • vue3如何直接修改reactive定義的變量

    vue3如何直接修改reactive定義的變量

    這篇文章主要介紹了vue3如何直接修改reactive定義的變量問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-05-05
  • 如何在vue里添加好看的lottie動畫

    如何在vue里添加好看的lottie動畫

    這篇文章主要介紹了在vue里添加好看的lottie動畫效果的方法,在vue中引入lottie非常簡單,需要的朋友可以參考下
    2018-08-08
  • 超級詳細(xì)的Vue安裝與配置教程

    超級詳細(xì)的Vue安裝與配置教程

    Vue web前端三大主流框架之一,是一套用于構(gòu)建用戶界面的漸進(jìn)式框架,下面這篇文章主要給大家介紹了關(guān)于Vue安裝與配置教程的相關(guān)資料,文中通過圖文介紹的非常詳細(xì),需要的朋友可以參考下
    2022-06-06

最新評論

新闻| 福海县| 抚顺市| 闽清县| 阳原县| 天峨县| 铜鼓县| 顺昌县| 连江县| 开封市| 壤塘县| 津市市| 上林县| 宜宾县| 若尔盖县| 盐源县| 大荔县| 易门县| 三穗县| 和硕县| 乡城县| 商都县| 壶关县| 巴南区| 东乡县| 乐昌市| 青海省| 建湖县| 徐闻县| 盖州市| 绍兴市| 衡阳市| 太保市| 赤峰市| 永胜县| 光山县| 东明县| 贵定县| 乌拉特前旗| 关岭| 东台市|