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

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

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

以上就是uni app跨端自定義指令實(shí)現(xiàn)按鈕權(quán)限的詳細(xì)內(nèi)容,更多關(guān)于uni app跨端自定義按鈕權(quán)限的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
from 表單提交返回值用post或者是get方法實(shí)現(xiàn)
from 表單提交的返回值可以用jquery的post或者是get方法去實(shí)現(xiàn),具體如下,感興趣的朋友可以參考下,希望對(duì)大家有所幫助2013-08-08
js+css實(shí)現(xiàn)select的美化效果
這篇文章主要為大家詳細(xì)介紹了js+css實(shí)現(xiàn)select的美化效果,如何針對(duì)select進(jìn)行美化,感興趣的小伙伴們可以參考一下2016-03-03
JavaScript 處理樹數(shù)據(jù)結(jié)構(gòu)的方法示例
這篇文章主要介紹了JavaScript 處理樹數(shù)據(jù)結(jié)構(gòu)的方法示例,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2019-06-06
Javascript和Java獲取各種form表單信息的簡單實(shí)例
本篇文章主要是對(duì)Javascript和Java獲取各種form表單信息的簡單實(shí)例進(jìn)行了介紹,需要的朋友可以過來參考下,希望對(duì)大家有所幫助2014-02-02
JavaScript開發(fā)人員的10個(gè)關(guān)鍵習(xí)慣小結(jié)
還在一味沒有目的的編寫JavaScript代碼嗎?那么你就OUT了!讓我們一起來看看小編為大家搜羅的JavaScript開發(fā)人員應(yīng)該具備的十大關(guān)鍵習(xí)慣吧2014-12-12
js 實(shí)現(xiàn)菜單左右滾動(dòng)顯示示例介紹
菜單左右滾動(dòng)顯示的實(shí)現(xiàn)方法有很多,在本文將為大家介紹下如何使用js實(shí)現(xiàn),需要的朋友可以參考下,希望對(duì)大家有所幫助2013-11-11

