vue 自定義指令directive的使用場(chǎng)景
1. 一個(gè)指令定義對(duì)象可以提供如下幾個(gè)鉤子函數(shù)(均為可選)
- bind:只調(diào)用一次,指令第一次綁定到元素時(shí)調(diào)用。在這里可以進(jìn)行一次性的初始化設(shè)置。
- inserted:被綁定元素插入父節(jié)點(diǎn)時(shí)調(diào)用(僅保證父節(jié)點(diǎn)存在,但不一定已被插入文檔中)。
- update:只要當(dāng)前元素不被移除,其他操作幾乎都會(huì)觸發(fā)這2個(gè)生命周期,先觸發(fā)update后觸發(fā)componentUpdate。虛擬DOM什么時(shí)候更新:只要涉及到元素的隱藏、顯示(display)值的改變、內(nèi)容的改變等都會(huì)觸發(fā)虛擬DOM更新.
- componentUpdated:組件更新
- unbind:當(dāng)使用指令的元素被卸載的時(shí)候會(huì)執(zhí)行,就是當(dāng)前元素被移除的時(shí)候,只調(diào)用一次
Vue.directive 內(nèi)置了五個(gè)鉤子函數(shù) :
bind(綁定觸發(fā))、inserted(插入觸發(fā))、update(更新觸發(fā))、componentUpdated(組件更新觸發(fā))和unbind(解綁觸發(fā))函
// 注冊(cè)
Vue.directive('my-directive',{
bind: function () {},
inserted: function () {},
update: function () {},
componentUpdated: function () {},
unbind: function() {}
})
2.指令鉤子函數(shù)會(huì)被傳入以下參數(shù)
- el:指定所綁定的元素,可以用來(lái)直接操作DOM
- binding:一個(gè)對(duì)象,包含以下屬性:
- name:指令名,不包含前綴v-
- value:指令的綁定值,例如:v-my-directive="1+1"中,綁定值為2
- oldValue:指令綁定的前一個(gè)值,僅在update和componentUpdated鉤子中可用,無(wú)論值是否改變都可用。
- expression: 綁定值的字符串形式。 例如 v-my-directive=“1 + 1” , expression 的值是 “1 + 1”。
- arg: 傳給指令的參數(shù)。例如 v-my-directive:foo, arg 的值是 “foo”。
- modifiers: 一個(gè)包含修飾符的對(duì)象。 例如: v-my-directive.foo.bar, 修飾符對(duì)象 modifiers 的值是{ foo: true, bar: true }。
- vnode: Vue 編譯生成的虛擬節(jié)點(diǎn)
- oldVnode: 上一個(gè)虛擬節(jié)點(diǎn),僅在 update 和 componentUpdated 鉤子中可用
- vnode:vue編譯生成的虛擬節(jié)點(diǎn)
- oldVnode:上一個(gè)虛擬節(jié)點(diǎn),僅在update和componentUpdated鉤子中可用
除了el之外,其他參數(shù)都應(yīng)該是只讀的,不能修改。如果需要在鉤子之間共享數(shù)據(jù),建議通過(guò)元素的 dataset 來(lái)進(jìn)行。
3.使用自定義指令場(chǎng)景的示例
drag.js
import Vue from 'vue'
import { Message } from 'element-ui';
// 自定義指令示例1:彈窗拖拽
Vue.directive('dialogDrag',{
bind(el,binding,vnode,oldVnode){
const dialogHeader = el.querySelector('.el-dialog__header');
const dialogDom = el.querySelector('.el-dialog');
dialogHeader.style.cursor = 'move'
/**
* 不同瀏覽器獲取行內(nèi)樣式屬性
* ie瀏覽器: dom元素.currentStyle
* 火狐瀏覽器:window.getComputedStyle(dom元素, null)
*/
const sty = dialogDom.currentStyle || window.getComputedStyle(dialogDom, null)
dialogHeader.onmousedown = (e) => {
//按下鼠標(biāo),獲取點(diǎn)擊的位置 距離 彈窗的左邊和上邊的距離
//點(diǎn)擊的點(diǎn)距離左邊窗口的距離 - 彈窗距離左邊窗口的距離
const distX = e.clientX - dialogHeader.offsetLeft;
const distY = e.clientY - dialogHeader.offsetTop;
//彈窗的left屬性值和top屬性值
let styL, styT
//注意在ie中,第一次獲取到的值為組件自帶50%,移動(dòng)之后賦值為Px
if(sty.left.includes('%')){
styL = +document.body.clientWidth * (+sty.left.replace(/%/g,'') / 100)
styT = +document,body.clientHeight * (+sty.top.replace(/%/g,'') / 100)
}else{
styL = +sty.left.replace(/px/g,'');
styT = +sty.top.replace(/px/g,'');
}
document.onmousemove = function(e) {
//通過(guò)事件委托,計(jì)算移動(dòng)距離
const l = e.clientX - distX
const t = e.clientY - distY
//移動(dòng)當(dāng)前的元素
dialogDom.style.left = `${l + styL}px`
dialogDom.style.top = `${t + styT}px`
}
document.onmouseup = function(e){
document.onmousemove = null
document.onmouseup = null
}
}
}
})
//自定義指令示例2:v-dialogDragWidth 可拖動(dòng)彈窗寬度(右側(cè)邊)
Vue.directive('dragWidth',{
bind(el) {
const dragDom = el.querySelector('.el-dialog');
const lineEl = document.createElement('div');
lineEl.style = 'width: 5px; background: inherit; height: 80%; position: absolute; right: 0; top: 0; bottom: 0; margin: auto; z-index: 1; cursor: w-resize;';
lineEl.addEventListener('mousedown',
function (e) {
// 鼠標(biāo)按下,計(jì)算當(dāng)前元素距離可視區(qū)的距離
const disX = e.clientX - el.offsetLeft;
// 當(dāng)前寬度
const curWidth = dragDom.offsetWidth;
document.onmousemove = function (e) {
e.preventDefault(); // 移動(dòng)時(shí)禁用默認(rèn)事件
// 通過(guò)事件委托,計(jì)算移動(dòng)的距離
const l = e.clientX - disX;
if(l > 0){
dragDom.style.width = `${curWidth + l}px`;
}
};
document.onmouseup = function (e) {
document.onmousemove = null;
document.onmouseup = null;
};
}, false);
dragDom.appendChild(lineEl);
}
})
// 自定義指令示例3:v-dialogDragWidth 可拖動(dòng)彈窗高度(右下角)
Vue.directive('dragHeight',{
bind(el) {
const dragDom = el.querySelector('.el-dialog');
const lineEl = document.createElement('div');
lineEl.style = 'width: 6px; background: inherit; height: 10px; position: absolute; right: 0; bottom: 0; margin: auto; z-index: 1; cursor: nwse-resize;';
lineEl.addEventListener('mousedown',
function(e) {
// 鼠標(biāo)按下,計(jì)算當(dāng)前元素距離可視區(qū)的距離
const disX = e.clientX - el.offsetLeft;
const disY = e.clientY - el.offsetTop;
// 當(dāng)前寬度 高度
const curWidth = dragDom.offsetWidth;
const curHeight = dragDom.offsetHeight;
document.onmousemove = function(e) {
e.preventDefault(); // 移動(dòng)時(shí)禁用默認(rèn)事件
// 通過(guò)事件委托,計(jì)算移動(dòng)的距離
const xl = e.clientX - disX;
const yl = e.clientY - disY
dragDom.style.width = `${curWidth + xl}px`;
dragDom.style.height = `${curHeight + yl}px`;
};
document.onmouseup = function(e) {
document.onmousemove = null;
document.onmouseup = null;
};
}, false);
dragDom.appendChild(lineEl);
}
})
// 自定義指令示例4:圖片加載前填充背景色
Vue.directive('imgUrl',function(el,binding){
var color=Math.floor(Math.random()*1000000);//設(shè)置隨機(jī)顏色
el.style.backgroundColor='#'+color;
var img=new Image();
img.src=binding.value;// -->binding.value指的是指令后的參數(shù)
img.onload=function(){
el.style.backgroundColor='';
el.src=binding.value;
}
})
// 自定義指令示例5:輸入框聚焦
Vue.directive("focus", {
// 當(dāng)被綁定的元素插入到 DOM 中時(shí)……
inserted (el) {
// 聚焦元素
el.querySelector('input').focus()
},
});
// 自定義指令示例6:設(shè)置防抖自定義指令
Vue.directive('throttle', {
bind: (el, binding) => {
let setTime = binding.value; // 可設(shè)置防抖時(shí)間
if (!setTime) { // 用戶若不設(shè)置防抖時(shí)間,則默認(rèn)2s
setTime = 1000;
}
let cbFun;
el.addEventListener('click', event => {
if (!cbFun) { // 第一次執(zhí)行
cbFun = setTimeout(() => {
cbFun = null;
}, setTime);
} else {
/*如果多個(gè)事件監(jiān)聽(tīng)器被附加到相同元素的相同事件類型上,當(dāng)此事件觸發(fā)時(shí),
它們會(huì)按其被添加的順序被調(diào)用。如果在其中一個(gè)事件監(jiān)聽(tīng)器中執(zhí)行 stopImmediatePropagation() ,那么剩下的事件監(jiān)聽(tīng)器都不會(huì)被調(diào)用*/
event && event.stopImmediatePropagation();
}
}, true);
},
});
// 自定義指令示例7:點(diǎn)擊按鈕操作頻繁給出提示
Vue.directive('preventReClick', {
inserted: function (el, binding) {
el.addEventListener('click', () => {
if (!el.disabled) {
el.disabled = true
Message.warning('操作頻繁')
setTimeout(() => {
el.disabled = false
//可設(shè)置時(shí)間
}, binding.value || 3000)
}
})
}
})
main.js中引入文件:
import '@/assets/js/drag.js'
頁(yè)面使用:
<template>
<div>
<el-button type="text" @click="dialogVisible = true">點(diǎn)擊打開(kāi) Dialog</el-button>
<div style="display:flex">
<img v-imgUrl="url"></img>
<img v-imgUrl="url"></img>
<img v-imgUrl="url"></img>
<img v-imgUrl="url"></img>
<img v-imgUrl="url"></img>
<img v-imgUrl="url"></img>
<img v-imgUrl="url"></img>
<img v-imgUrl="url"></img>
</div>
<div>
<el-input placeholder="請(qǐng)選擇日期" suffix-icon="el-icon-date" v-model="input1"></el-input>
<el-input v-focus placeholder="請(qǐng)輸入內(nèi)容" prefix-icon="el-icon-search" v-model="input2"></el-input>
</div>
<div>
<el-button type="danger" v-throttle @click="throttleBtn">危險(xiǎn)按鈕</el-button>
<el-button @click="submitForm()">創(chuàng)建</el-button>
</div>
<el-dialog title="提示" v-dialogDrag v-dragWidth v-dragHeight :visible.sync="dialogVisible" width="30%" :before-close="handleClose">
<span>這是一段信息</span>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false">取 消</el-button>
<el-button type="primary" @click="dialogVisible = false">確 定</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
export default {
data() {
return {
dialogVisible: false,
url:'//www.baidu.com/img/flexible/logo/pc/result.png',
input1: '',
input2: '',
}
},
methods: {
handleClose(done) {
console.log('彈窗打開(kāi)')
},
throttleBtn(){
console.log('我的用來(lái)測(cè)試防抖的按鈕')
},
submitForm(){
this.$message.error('Message 消息提示每次只能1個(gè)');
}
},
}
</script>
<style>
img{
width: 100px;
height: 100px;
}
</style>
看下效果吧:
首先進(jìn)入頁(yè)面,
- 第二個(gè)輸入框會(huì)鼠標(biāo)聚焦,
- 點(diǎn)擊按鈕,會(huì)有防止重復(fù)點(diǎn)擊
- 圖片加載前有默認(rèn)背景色
- 彈窗 可以隨處移動(dòng)。右邊可拖拽變寬,右下角可以整體變大

到此這篇關(guān)于vue 自定義指令directive的使用場(chǎng)景的文章就介紹到這了,更多相關(guān)vue 自定義指令directive內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
js判斷背景圖片是否加載成功使用img的width實(shí)現(xiàn)
判斷背景圖片是否加載成功想必大家對(duì)此很陌生吧,會(huì)了之后就可以判斷css背景圖片了,具體判斷代碼如下,感興趣的朋友可以參考下哈2013-05-05
關(guān)于TypeScript應(yīng)該盡量避免的語(yǔ)法總結(jié)
TypeScript是JavaScript的超集,具有類型系統(tǒng),支持ES6語(yǔ)法,支持面向?qū)ο缶幊痰母拍?下面這篇文章主要給大家介紹了關(guān)于TypeScript應(yīng)該盡量避免的語(yǔ)法,需要的朋友可以參考下2022-04-04
javaScript強(qiáng)制保留兩位小數(shù)的輸入數(shù)校驗(yàn)和小數(shù)保留問(wèn)題
這篇文章主要介紹了javaScript強(qiáng)制保留兩位小數(shù)的輸入數(shù)校驗(yàn)和小數(shù)保留問(wèn)題,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2018-05-05
JS實(shí)現(xiàn)頁(yè)面鼠標(biāo)點(diǎn)擊出現(xiàn)圖片特效
這篇文章主要為大家詳細(xì)介紹了JS實(shí)現(xiàn)頁(yè)面鼠標(biāo)點(diǎn)擊出現(xiàn)圖片特效,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-08-08
微信小程序的運(yùn)行機(jī)制與安全機(jī)制解決方案詳解
這篇文章主要介紹了微信小程序的運(yùn)行機(jī)制與安全機(jī)制解決方案,接觸小程序有一段時(shí)間了,總得來(lái)說(shuō)小程序開(kāi)發(fā)門(mén)檻比較低,但其中基本的運(yùn)行機(jī)制和原理還是要懂的2023-02-02
前端音頻可視化Web?Audio實(shí)現(xiàn)示例詳解
這篇文章主要為大家介紹了前端音頻可視化Web?Audio實(shí)現(xiàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-03-03
如何用js實(shí)現(xiàn)鼠標(biāo)向上滾動(dòng)時(shí)浮動(dòng)導(dǎo)航
今天給大家介紹一下使用JavaScript判斷鼠標(biāo)滑輪是不是向上滾動(dòng),當(dāng)向上滾動(dòng)的時(shí)候,導(dǎo)航條浮動(dòng)在頂部位置。示例代碼如下。2016-07-07
基于JavaScript實(shí)現(xiàn)隨機(jī)顏色輸入框
這篇文章主要介紹了基于JavaScript實(shí)現(xiàn)隨機(jī)顏色輸入框的實(shí)例代碼,代碼簡(jiǎn)單易懂,非常不錯(cuò),需要的朋友參考下吧2016-12-12
bootstrap常用組件之頭部導(dǎo)航實(shí)現(xiàn)代碼
這篇文章主要介紹了bootstrap常用組件之頭部導(dǎo)航實(shí)現(xiàn)代碼,然后對(duì)個(gè)別常用屬性進(jìn)行了解釋,需要的的朋友參考下吧2017-04-04

