uni-app跨端自定義指令實(shí)現(xiàn)按鈕權(quán)限操作
前言
初看這個標(biāo)題可能很迷,uni-app明明不支持自定義指令,這文章是在搞笑嗎,本文對于uni-app自定義指令實(shí)現(xiàn)按鈕權(quán)限的方式也有可能是多余,但為了給業(yè)務(wù)部門更友好的開發(fā)體驗(yàn),還是做了一些可能沒意義的操作,讓移動端和PC端對于按鈕權(quán)限是使用方式一致,都是使用自定義指令的書寫方式來實(shí)現(xiàn)按鈕權(quán)限,雖然uni-app不支持自定義指令,但是我們有webpack的loader起到代碼轉(zhuǎn)換的作用,將自定義指令v-perms:add
在編譯階段轉(zhuǎn)換為v-if="$perms('add')"
,然后去處理$perms方法對于權(quán)限的判斷,就可以具有自定義指令實(shí)現(xiàn)按鈕權(quán)限的開發(fā)體驗(yàn)了。
每個工具的實(shí)現(xiàn)都不算簡單,本文實(shí)現(xiàn)的loader,盡管原理挺簡單的,好像可以一蹴而就,但真的去實(shí)現(xiàn)的話,發(fā)現(xiàn)還是需要很多的知識儲備,整體流程也沒想象的那么簡單,但有個點(diǎn)子就是好的開始,經(jīng)過些許努力,終將成就一個不錯的工具。
準(zhǔn)備
實(shí)現(xiàn)uni-app自定義指令按鈕權(quán)限需要涉及到對于vue.config.js新增loader配置,基礎(chǔ)正則知識,webpack的loader開發(fā)和調(diào)試,以及npm本地調(diào)試和發(fā)布,接下來就從了解這些前置知識開始。
目錄結(jié)構(gòu)
chainWebpack 新增loader
vue的loader配置是通過chainWebpack
來實(shí)現(xiàn)鏈?zhǔn)脚渲茫?code>vue.config.js新增一個loader配置可以查看vue-cli文檔,具體實(shí)現(xiàn):
// vue.config.js module.exports = {chainWebpack: config => {// GraphQL Loaderconfig.module.rule('graphql').test(/.graphql$/).use('graphql-tag/loader').loader('graphql-tag/loader').end()} }
正則
實(shí)現(xiàn)自定義指令替換,需要查找所有的v-perms:xxx
,并且需要拿到xxx
對應(yīng)的值,將其轉(zhuǎn)換為v-if="$perms('xxx')"
,所以就有了如下表達(dá)式,其作用就是匹配v-perms:xxx
表達(dá)式,并提取到xxx
內(nèi)容。
/v-perms:([^/<>\s]*)/g
針對正則基礎(chǔ)比較薄弱的同學(xué),我來解釋一下上面這個正則表達(dá)式:
- 首先,v-perms:用于匹配以v-perms:開頭的字符串
- 接著是(),()稱為捕獲組,其圈住的內(nèi)容,就是我們要捕獲起來額外存儲的東西。
- []中的匹配符之間是“或”的關(guān)系,也就是說只要能匹配上其中一個就行了。
- ^原本是匹配字符串的開始位置,但是在[]表達(dá)式中使用代表著除什么之外
- *跟在其它表達(dá)式后面,意味著“前面這個表達(dá)式可以出現(xiàn)0次或多次
- 最后這個/g表示該表達(dá)式將用來查找所有可能的匹配,返回的結(jié)果可以是多個,如果不加/g最多只會匹配一個
- 總結(jié)起來這個正則表達(dá)式的作用就是匹配以v-perms:開頭的所有內(nèi)容,并提取到v-perms:和空格、< 、>、/之間的內(nèi)容,可以適應(yīng)我們常寫的多個場景
// 結(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 包知識點(diǎn)
關(guān)于npm
包本地調(diào)試以及發(fā)布的知識點(diǎn)還是蠻重要的,寫一些工具庫,組件,腳手架都能用到,也是面試會考察到的點(diǎn),內(nèi)容比較多,可以看我之前寫的項目腳手架發(fā)布為npm包文章進(jìn)行學(xué)習(xí),這邊就講解一下npm
的本地調(diào)試。
npm link
執(zhí)行 npm link
,可以將本地npm包鏈接到全局的 node_modules
一些包沒辦法使用全局,那么我們可以執(zhí)行npm link packageName
將對應(yīng)包連接到當(dāng)前項目的node_modules
npm link packageName
執(zhí)行 npm unlink packageName
刪除本地連接
npm unlink packageName
loader 開發(fā)和調(diào)試
定義
Loader
只是一個導(dǎo)出為函數(shù)的JavaScript模塊。
最簡單的Loader
// source入?yún)⒕褪俏覀兣渲玫膶?yīng)規(guī)則匹配到文件類型的文件流或者上一個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返回之前對它進(jìn)行正則匹配和替換即可。
module.exports = function (source) {// TODO// 這里實(shí)現(xiàn)對于source的操作return source; };
module.exports = function (source) {// TODO// 這里實(shí)現(xiàn)對于source的操作return source; };
本地調(diào)試 ResolveLoader
webpack默認(rèn)情況下只會去 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文件新增一個uni-perms-loader的loaderchainWebpack: (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 自定義權(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)前項目根目錄下執(zhí)行npm link uni-perms-loader
,將uni-perms-loader
連接到本地node_modules
,uni-perms-loader 即使npm包名,我們在package.json配置的名稱name??梢栽诋?dāng)前項目的node_modules
中查到uni-perms-loader
。
vue.config.js 配置,這邊就不需要ResolveLoader了
// vue.config.js module.exports = {// 為.vue文件新增一個uni-perms-loader的loaderchainWebpack: (config) => {config.module.rule("vue").test(/\.vue$/).use("uni-perms-loader").loader("uni-perms-loader").end();}, };
本地調(diào)試是用于方便開發(fā)時對于loader進(jìn)行測試,在實(shí)際的應(yīng)用中還是發(fā)布為npm包,方便多個項目使用
完整代碼
這個loader的代碼還是很簡單,就是匹配到自定義指令,然后獲取對應(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開始,我們這邊只有一個,所以是$1,如果有// 多個,那就是$2,$3source = 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 配置
// 這邊是假數(shù)據(jù),不同團(tuán)隊對于權(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/indexconst { route } = pages[len - 1];// 判斷當(dāng)前頁面是否包含對應(yīng)按鈕的權(quán)限r(nóng)eturn !!data[`/${route}`][key]; }; export default checkPermission;
src/utils/index.js
按鈕權(quán)限判斷方式實(shí)現(xiàn)
import checkPermission from "./utils/index"; Vue.prototype.$perms = 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é)
本文對應(yīng)的uni-app使用uni-perms-loader的demo已經(jīng)提交到Github了, 對應(yīng)的uni-perms-loader
也發(fā)布到npm,這個loader算是比較簡單,大家可以自己實(shí)現(xiàn),也可以直接使用我發(fā)布的npm包。
這個loader可能不是必須的,但是有了它,可以有更好的開發(fā)體驗(yàn),也能和vue項目保持一致性,不算一無是處,具體是否使用,大家根據(jù)自己情況,有問題也歡迎探討。
到此這篇關(guān)于uni-app跨端自定義指令實(shí)現(xiàn)按鈕權(quán)限的文章就介紹到這了,更多相關(guān)uni-app按鈕權(quán)限內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Javascript實(shí)現(xiàn)拖拽排序的代碼
這篇文章主要介紹了Javascript實(shí)現(xiàn)拖拽排序的代碼,本文在vue運(yùn)行環(huán)境下給大家演示下效果圖,對js拖拽排序?qū)嵗a感興趣的朋友跟隨小編一起看看吧2022-09-09JavaScript簡單實(shí)現(xiàn)的仿微博留言功能示例
這篇文章主要介紹了JavaScript簡單實(shí)現(xiàn)的仿微博留言功能,涉及javascript頁面元素屬性動態(tài)操作相關(guān)實(shí)現(xiàn)技巧,需要的朋友可以參考下2019-01-01layui實(shí)現(xiàn)數(shù)據(jù)表格隱藏列的示例
今天小編就為大家分享一篇layui實(shí)現(xiàn)數(shù)據(jù)表格隱藏列的示例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-10-10