uni?app跨端自定義指令實現(xiàn)按鈕權限
前言
初看這個標題可能很迷,uni-app明明不支持自定義指令,這文章是在搞笑嗎,本文對于uni-app自定義指令實現(xiàn)按鈕權限的方式也有可能是多余,但為了給業(yè)務部門更友好的開發(fā)體驗,還是做了一些可能沒意義的操作,讓移動端和PC端對于按鈕權限是使用方式一致,都是使用自定義指令的書寫方式來實現(xiàn)按鈕權限,雖然uni-app不支持自定義指令,但是我們有webpack的loader起到代碼轉換的作用,將自定義指令v-perms:add在編譯階段轉換為v-if="$perms('add')",然后去處理$perms方法對于權限的判斷,就可以具有自定義指令實現(xiàn)按鈕權限的開發(fā)體驗了。
每個工具的實現(xiàn)都不算簡單,本文實現(xiàn)的loader,盡管原理挺簡單的,好像可以一蹴而就,但真的去實現(xiàn)的話,發(fā)現(xiàn)還是需要很多的知識儲備,整體流程也沒想象的那么簡單,但有個點子就是好的開始,經(jīng)過些許努力,終將成就一個不錯的工具。
準備
實現(xiàn)uni-app自定義指令按鈕權限需要涉及到對于vue.config.js新增loader配置,基礎正則知識,webpack的loader開發(fā)和調試,以及npm本地調試和發(fā)布,接下來就從了解這些前置知識開始。
目錄結構

chainWebpack 新增loader
vue的loader配置是通過chainWebpack來實現(xiàn)鏈式配置,vue.config.js新增一個loader配置可以查看vue-cli文檔,具體實現(xiàn):
// vue.config.js
module.exports = {
chainWebpack: config => {
// GraphQL Loader
config.module
.rule('graphql')
.test(/.graphql$/)
.use('graphql-tag/loader')
.loader('graphql-tag/loader')
.end()
}
}
正則
實現(xiàn)自定義指令替換,需要查找所有的v-perms:xxx,并且需要拿到xxx對應的值,將其轉換為v-if="$perms('xxx')",所以就有了如下表達式,其作用就是匹配v-perms:xxx表達式,并提取到xxx內容。
/v-perms:([^/<>\s]*)/g
針對正則基礎比較薄弱的同學,我來解釋一下上面這個正則表達式:
- 首先,
v-perms:用于匹配以v-perms:開頭的字符串 - 接著是
(),()稱為捕獲組,其圈住的內容,就是我們要捕獲起來額外存儲的東西。 []中的匹配符之間是“或”的關系,也就是說只要能匹配上其中一個就行了。^原本是匹配字符串的開始位置,但是在[]表達式中使用代表著除什么之外*跟在其它表達式后面,意味著“前面這個表達式可以出現(xiàn)0次或多次- 最后這個
/g表示該表達式將用來查找所有可能的匹配,返回的結果可以是多個,如果不加/g最多只會匹配一個 - 總結起來這個正則表達式的作用就是匹配以
v-perms:開頭的所有內容,并提取到v-perms:和空格、< 、>、/之間的內容,可以適應我們常寫的多個場景
// 結尾是">" <button v-perms:add>新增按鈕</button> // 結尾是"/" <input v-perms:add/> // 結尾是空格 <button v-perms:add class="btn">新增按鈕 v-perms:add</button> // 結尾是"<" <button>新增按鈕 v-perms:add</button>
npm 包知識點
關于npm包本地調試以及發(fā)布的知識點還是蠻重要的,寫一些工具庫,組件,腳手架都能用到,也是面試會考察到的點,內容比較多,可以看我之前寫的項目腳手架發(fā)布為npm包文章進行學習,這邊就講解一下npm的本地調試。
npm link
執(zhí)行 npm link,可以將本地npm包鏈接到全局的 node_modules
一些包沒辦法使用全局,那么我們可以執(zhí)行npm link packageName將對應包連接到當前項目的node_modules
npm link packageName
執(zhí)行 npm unlink packageName 刪除本地連接
npm unlink packageName
loader 開發(fā)和調試
定義
Loader只是一個導出為函數(shù)的JavaScript模塊。
最簡單的Loader
// source入?yún)⒕褪俏覀兣渲玫膶?guī)則匹配到文件類型的文件流或者上一個loader處理后的結果。
module.exports = function (source) {
return source;
};
Loader基礎操作
例如我們的.vue文件中包含如下代碼:
<u-button type="success" v-perms:edit>編輯</u-button>
我們需要將模板的v-perms:edit替換成v-if="$perms('edit')",只需要在source返回之前對它進行正則匹配和替換即可。
<u-button type="success" v-if="$perms('edit')">編輯</u-button>
module.exports = function (source) {
// TODO
// 這里實現(xiàn)對于source的操作
return source;
};
本地調試
ResolveLoader
webpack默認情況下只會去 node_modules 目錄下尋找loader,但是我們可以通過ResolveLoader.modules配置loader的加載目錄,通過上述的目錄結構可以看出我將loader寫在根目錄的loaders下,所以可以有如下配置。
// vue.config.js
module.exports = {
configureWebpack: {
resolveLoader: {
// 配置loader可以從node_modules和loaders目錄下查找
modules: ["node_modules", "./loaders/"],
},
},
// 為.vue文件新增一個uni-perms-loader的loader
chainWebpack: (config) => {
config.module
.rule("vue")
.test(/\.vue$/)
.use("uni-perms-loader")
.loader("uni-perms-loader")
.end();
},
};
npm link
- 在
/loaders/uni-perms-loader目錄下執(zhí)行npm link,將uni-perms-loader連接到全局,執(zhí)行時需要配置好package.json,具體配置可以查看文章。
{
"name": "uni-perms-loader", // 包名
"version": "1.0.0", // 版本號
"description": "uni-app 自定義權限指令替換", // 介紹
"main": "index.js", // 入口
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [ // npm包搜索關鍵詞
"uni-app",
"自定義指令",
"directive"
],
"author": "LBINGXIN",
"license": "MIT" // 開源協(xié)議
}
- 在當前項目根目錄下執(zhí)行
npm link uni-perms-loader,將uni-perms-loader連接到本地node_modules,uni-perms-loader 即使npm包名,我們在package.json配置的名稱name??梢栽诋斍绊椖康?code>node_modules中查到uni-perms-loader。

- vue.config.js 配置,這邊就不需要ResolveLoader了
// vue.config.js
module.exports = {
// 為.vue文件新增一個uni-perms-loader的loader
chainWebpack: (config) => {
config.module
.rule("vue")
.test(/\.vue$/)
.use("uni-perms-loader")
.loader("uni-perms-loader")
.end();
},
};
本地調試是用于方便開發(fā)時對于loader進行測試,在實際的應用中還是發(fā)布為npm包,方便多個項目使用
完整代碼
這個loader的代碼還是很簡單,就是匹配到自定義指令,然后獲取對應參數(shù),然后替換成v-if
loaders/uni-perms-loader/index.js
uni-perms-loader具體實現(xiàn)
function replaceDirective(source) {
// 正則表達式
const reg = /v-perms:([^/<>\s]*)/g;
// 使用replace實現(xiàn)字符串替換
// 這邊的$n就是指捕獲組()匹配的內容,索引是從1開始,我們這邊只有一個,所以是$1,如果有
// 多個,那就是$2,$3
source = source.replace(reg, `v-if="$perms('$1')"`);
return source;
}
module.exports = function (source) {
// 處理替換
source = replaceDirective(source);
return source;
};
loaders/uni-perms-loader/package.json
package.json 配置
{
"name": "uni-perms-loader",
"version": "1.0.0",
"description": "uni-app 自定義權限指令替換",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [
"uni-app",
"自定義指令",
"directive"
],
"author": "LBINGXIN",
"license": "MIT"
}
src/utils/index.js
按鈕權限判斷方式實現(xiàn)
// 這邊是假數(shù)據(jù),不同團隊對于權限的數(shù)據(jù)定義都不大一樣,我列舉的算是最簡單的一種,不大需要
// 去考慮不同頁面按鈕名稱重復,用當前頁面路由進行區(qū)分
const data = {
"/pages/index/index": {
add: "新增",
edit: "編輯",
},
"/pages/me/index": {
add: "新增",
auth: "授權",
},
};
const checkPermission = (key) => {
// 獲取所有路由棧
const pages = getCurrentPages();
const len = pages.length;
// 獲取當前頁面路由 route的值例如 pages/index/index
const { route } = pages[len - 1];
// 判斷當前頁面是否包含對應按鈕的權限
return !!data[`/${route}`][key];
};
export default checkPermission;
main.js
將實現(xiàn)按鈕權限判斷的函數(shù)掛載到全局的$perms上
import checkPermission from "./utils/index"; Vue.prototype.$perms = checkPermission;
使用
<template>
<view class="content">
<image class="logo" src="/static/logo.png"></image>
<view class="buttons">
<u-button type="primary" v-perms:add>新增 </u-button>
<u-button type="success" v-perms:edit>編輯</u-button>
<u-button type="error" v-perms:delete>刪除</u-button>
<u-button type="warning" v-perms:auth>授權</u-button>
</view>
</view>
</template>
小結
本文對應的uni-app使用uni-perms-loader的demo已經(jīng)提交到Github了, 對應的uni-perms-loader也發(fā)布到npm,這個loader算是比較簡單,大家可以自己實現(xiàn),也可以直接使用我發(fā)布的npm包。
這個loader可能不是必須的,但是有了它,可以有更好的開發(fā)體驗,也能和vue項目保持一致性,不算一無是處,具體是否使用,大家根據(jù)自己情況,有問題也歡迎探討。

以上就是uni app跨端自定義指令實現(xiàn)按鈕權限的詳細內容,更多關于uni app跨端自定義按鈕權限的資料請關注腳本之家其它相關文章!
相關文章
詳解Webpack實戰(zhàn)之構建 Electron 應用
本篇文章主要介紹了Webpack實戰(zhàn)之構建 Electron 應用,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-12-12
bootstrap3使用bootstrap datetimepicker日期插件
這篇文章主要為大家詳細介紹了bootstrap3中使用bootstrap datetimepicker日期插件的用法,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-05-05

