vue自定義封裝指令以及實(shí)際使用
前言
vue默認(rèn)內(nèi)置了v-model、v-if、v-show、v-html、v-text等指令,但是這些往往不足以滿足我們實(shí)際項(xiàng)目開(kāi)發(fā)中的場(chǎng)景,比如權(quán)限控制按鈕、路由菜單,復(fù)制文字等功能,就需要我們自己自定義一些滿足我們項(xiàng)目需求的指令了,那怎么封裝自定義指令,并使用呢?我們先從封裝指令的基礎(chǔ)說(shuō)起。
封裝指令基礎(chǔ)
鉤子函數(shù)
- bind:只調(diào)用一次,指令第一次綁定到元素時(shí)調(diào)用??梢赃M(jìn)行一次性初始化設(shè)置。
- inserted:被綁定元素插入父節(jié)點(diǎn)時(shí)調(diào)用(僅保證父節(jié)點(diǎn)存在,但不一定已經(jīng)被插入文檔中)。
- update:所在組件的VNode更新時(shí)調(diào)用,也可能發(fā)生在其子VNode更新之前。
- componentUpdated:指令所在組件的VNode及其子VNode全部更新后調(diào)用。
- unbind:只調(diào)用一次,指令與元素解綁時(shí)調(diào)用。
鉤子函數(shù)參數(shù)
鉤子函數(shù)參數(shù)包含了el、binding、vnode、oldVnode。
- el:指令所綁定的元素,可以用來(lái)直接操作DOM。
- binding:一個(gè)對(duì)象,包含以下屬性
- name:指令名。不包括v-前綴(如:v-copy的name為copy)。
- value:指令的綁定值(如:v-copy='1 + 1'中,value值為2)。
- oldValue:指令綁定的前一個(gè)值,僅在update和componentUpdated鉤子函數(shù)中可用,無(wú)論值是否改變都可用。
- expression:字符串形式的指令表達(dá)式(如:v-copy='1 + 1',表達(dá)式為"1 + 1")。
- arg:傳給指令的參數(shù)(如:v-copy:dblclick中,arg的值為dblclick)。
- modifiers:一個(gè)包含修飾符的對(duì)象(如:v-copy.dblclick.icon中,修飾符對(duì)象為:{dblclick: true, icon: true})。
- vnode:Vue編譯生成的虛擬節(jié)點(diǎn)。
- oldVnode:上一個(gè)虛擬節(jié)點(diǎn)。僅在update和componentUpdated鉤子函數(shù)中可用。
實(shí)際使用
復(fù)制指令(v-copy)
我們先看如何使用:
單擊復(fù)制
<div v-copy>單擊復(fù)制</div> // 默認(rèn)復(fù)制div的文案 <div v-copy="copyStr">單擊復(fù)制</div> // 復(fù)制指令里的內(nèi)容(copyStr)
給el添加點(diǎn)擊事件,判斷binding的value值是否為空,若為空,默認(rèn)獲取綁定元素的文本內(nèi)容
el.addEventListener("click", () => { let str = binding.value ? binding.value : el.innerText; handleClick(str); }); el.style.cursor = "copy";
雙擊復(fù)制
<div v-copy:dblclick>雙擊復(fù)制</div> // 默認(rèn)復(fù)制div的文案 <div v-copy:dblclick="copyStr">雙擊復(fù)制</div> // 復(fù)制指令里的內(nèi)容(copyStr)
給el添加雙擊事件,判斷binding的value值是否為空,若為空,默認(rèn)獲取綁定元素的文本內(nèi)容
el.addEventListener("dblclick", () => { let str = binding.value ? binding.value : el.innerText; handleClick(str); }); el.style.cursor = "copy";
點(diǎn)擊icon復(fù)制
<div v-copy:icon>單擊icon復(fù)制</div> // 默認(rèn)復(fù)制div的文案 <div v-copy:icon="copyStr">單擊icon復(fù)制</div> // 復(fù)制指令里的內(nèi)容(copyStr)
判斷el是否已經(jīng)增加了icon,沒(méi)有則增加i標(biāo)簽,放置icon,給icon增加點(diǎn)擊事件,進(jìn)行復(fù)制
if (el.hasIcon) return; const iconElement = document.createElement("i"); iconElement.setAttribute("class", "el-icon-document-copy"); iconElement.setAttribute("style", "margin-left:5px"); el.appendChild(iconElement); el.hasIcon = true; iconElement.addEventListener("click", () => { let str = binding.value ? binding.value : el.innerText; handleClick(str); }); iconElement.style.cursor = "copy";
handleClick 邏輯
判斷是否有id為copyTarget的輸入框,沒(méi)有則創(chuàng)造一個(gè)id為copyTarget的輸入框,然后進(jìn)行選中,調(diào)用execCommand('copy')進(jìn)行選中文字的復(fù)制。
function handleClick (text) { if (!document.getElementById("copyTarget")) { const copyTarget = document.createElement("input"); copyTarget.setAttribute("id", "copyTarget"); copyTarget.setAttribute("style", "position:fixed;top:0;left:0;opacity:0;z-index:-1000;"); document.body.appendChild(copyTarget); } // 復(fù)制內(nèi)容 const input = document.getElementById("copyTarget"); input.value = text; input.select(); // 選取文本域中的內(nèi)容。 // 調(diào)用execCommand()可以實(shí)現(xiàn)瀏覽器菜單的很多功能. 如保存文件,打開(kāi)新文件,撤消、重做操作… document.execCommand("copy"); // 復(fù)制選中的文字到剪貼板; // Message.success("復(fù)制成功"); Notification({ title: "成功", message: `${text}已復(fù)制到剪切板`, type: "success" }); }
完整代碼
import { Message, Notification } from "element-ui"; function handleClick (text) { if (!document.getElementById("copyTarget")) { const copyTarget = document.createElement("input"); copyTarget.setAttribute("id", "copyTarget"); copyTarget.setAttribute("style", "position:fixed;top:0;left:0;opacity:0;z-index:-1000;"); document.body.appendChild(copyTarget); } // 復(fù)制內(nèi)容 const input = document.getElementById("copyTarget"); input.value = text; input.select(); // 選取文本域中的內(nèi)容。 // 調(diào)用execCommand()可以實(shí)現(xiàn)瀏覽器菜單的很多功能. 如保存文件,打開(kāi)新文件,撤消、重做操作… document.execCommand("copy"); // 復(fù)制選中的文字到剪貼板; // Message.success("復(fù)制成功"); Notification({ title: "成功", message: `${text}已復(fù)制到剪切板`, type: "success" }); } const install = function (Vue) { Vue.directive("copy", { bind (el, binding) { if (binding.arg === "dblclick") { // 雙擊觸發(fā) el.addEventListener("dblclick", () => { let str = binding.value ? binding.value : el.innerText; handleClick(str); }); el.style.cursor = "copy"; } else if (binding.arg === "icon") { // 點(diǎn)擊icon觸發(fā) if (el.hasIcon) return; const iconElement = document.createElement("i"); iconElement.setAttribute("class", "el-icon-document-copy"); iconElement.setAttribute("style", "margin-left:5px"); el.appendChild(iconElement); el.hasIcon = true; iconElement.addEventListener("click", () => { let str = binding.value ? binding.value : el.innerText; handleClick(str); }); iconElement.style.cursor = "copy"; } else { // 單擊觸發(fā) el.addEventListener("click", () => { let str = binding.value ? binding.value : el.innerText; handleClick(str); }); el.style.cursor = "copy"; } } }); }; export default install;
權(quán)限操作指令(v-hasPermi)
- 使用:
<el-button v-hasPermi="['activity:school:add']">新增活動(dòng)</el-button>
- 從store獲取用戶的權(quán)限數(shù)組,判斷此時(shí)binding的value值是否存在權(quán)限數(shù)組中,沒(méi)有則進(jìn)行按鈕的隱藏。
- 完整代碼
import store from "@/store"; const allPermission = "*:*:*"; export function hasPermi(value){ // return true; const permissions = store.getters && store.getters.permissions; if (value && value instanceof Array && value.length > 0) { const permissionFlag = value; const hasPermissions = permissions.some(permission => allPermission === permission || permissionFlag.includes(permission)); if (!hasPermissions) { return false; } return true; } throw new Error("請(qǐng)?jiān)O(shè)置操作權(quán)限標(biāo)簽值"); } export default { inserted(el, binding) { const { value } = binding; if (!hasPermi(value)){ el.parentNode && el.parentNode.removeChild(el); } } };
總結(jié)
到此這篇關(guān)于vue自定義封裝指令以及實(shí)際使用的文章就介紹到這了,更多相關(guān)vue自定義封裝指令內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
vue+echarts+datav大屏數(shù)據(jù)展示及實(shí)現(xiàn)中國(guó)地圖省市縣下鉆功能
這篇文章主要介紹了vue+echarts+datav大屏數(shù)據(jù)展示及實(shí)現(xiàn)中國(guó)地圖省市縣下鉆,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-11-11Vue3?echarts組件化及使用hook進(jìn)行resize方式
這篇文章主要介紹了Vue3?echarts組件化及使用hook進(jìn)行resize方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-04-04SpringBoot+Vue開(kāi)發(fā)之Login校驗(yàn)規(guī)則、實(shí)現(xiàn)登錄和重置事件
這篇文章主要介紹了SpringBoot+Vue開(kāi)發(fā)之Login校驗(yàn)規(guī)則、實(shí)現(xiàn)登錄和重置事件,本文通過(guò)圖文實(shí)例相結(jié)合給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-10-10Vue高性能列表GridList組件及實(shí)現(xiàn)思路詳解
這篇文章主要為大家介紹了Vue高性能列表GridList組件及實(shí)現(xiàn)思路詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-11-11Vue使用axios出現(xiàn)options請(qǐng)求方法
這篇文章主要介紹了Vue使用axios出現(xiàn)options請(qǐng)求,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-05-05淺談ElementUI el-select 數(shù)據(jù)過(guò)多解決辦法
下拉框的選項(xiàng)很多,上萬(wàn)個(gè)選項(xiàng)甚至更多,這個(gè)時(shí)候如果全部把數(shù)據(jù)放到下拉框中渲染出來(lái),瀏覽器會(huì)卡死,體驗(yàn)會(huì)特別不好,本文主要介紹了ElementUI el-select 數(shù)據(jù)過(guò)多解決辦法,感興趣的可以了解一下2021-09-09使用vue.js開(kāi)發(fā)時(shí)一些注意事項(xiàng)
使用vue.js進(jìn)行項(xiàng)目的開(kāi)發(fā)已經(jīng)有了一定的時(shí)間,在任務(wù)的過(guò)程中以及和不同的開(kāi)發(fā)使用者交流中,逐漸對(duì)vue.js的使用心得有了一定的積累。本文主要給大家分享一些開(kāi)發(fā)時(shí)需要注意的事項(xiàng)2016-04-04vue項(xiàng)目中路由懶加載的三種方式(簡(jiǎn)潔易懂)
本文主要介紹了vue項(xiàng)目中路由懶加載的三種方式,主要包括vue異步組件,組件懶加載,webpack的require.ensure(),具有一定的參考價(jià)值,感興趣的可以了解一下2024-01-01vue中echarts圖表大小適應(yīng)窗口大小且不需要刷新案例
這篇文章主要介紹了vue中echarts圖表大小適應(yīng)窗口大小且不需要刷新案例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-07-07