全局注册
全局注册通过Vue.directive方法进行注册
Vue.directive(指令名称, {
/**
* 只调用一次,指令第一次绑定到元素时被调用,在这里可以进行一次性的初始化设置
* @param {*} el 指令嗦绑定的元素 dom
* @param {*} binding 指令信息
* @param {*} vnode 虚拟节点
* @param {*} oldVnode 旧虚拟节点 仅在 update 和 componentUpdated 钩子中可用
*/
bind(el, binding, vnode, oldVnode) {
const { value } = binding; // 传递过来的参数
},
// 被绑定的元素插入父节点时调用
inserted(el, binding, vnode, oldVnode) {
console.log("inserted阶段", el, binding, vnode, oldVnode);
},
// 所在组件的VNdeo更新是调用,但是可能发生在其子VNode更新之前
update(el, binding, vnode, oldVnode) {
const { value } = binding
el.style.color = value
console.log("update阶段", el, binding, vnode, oldVnode);
},
// 在所在组件的VNode及其子VNode全部更新后调用
componentUpdated(el, binding, vnode, oldVnode) {
console.log("componentUpdated阶段", el, binding, vnode, oldVnode);
},
// 只调用一次 指令与元素解绑时调用
unbind(el, binding, vnode, oldVnode) {
console.log("unbind阶段", el, binding, vnode, oldVnode);
}
})
例子-点击复制
// copy.js
function handler(binding) {
const text = document.createElement("input");
text.setAttribute("value", binding.value);
document.body.appendChild(text);
text.select();
try {
document.execCommand('copy');
alert("复制成功")
} catch (error) {
alert("您的浏览器不支持点击复制到剪贴板");
}
text.remove();
}
export default {
inserted(el, binding) {
el.addEventListener("click", () => {
handler(binding)
})
},
unbind(el) {
el.removeEventListener("click", () => {
handler(binding)
});
}
}
// 注册自定义指令(copy.js)
import copy from "copy.js";
Vue.directive("copy", copy);
// index.vue 中使用
<template>
<div>
<button v-copy="copyContent">复制指令</button>
</div>
</template>
<script>
export default {
data() {
return {
copyContent: "这是复制的内容"
}
}
}
</script>
例子-点击防抖
// debounce.js
function handler(callback, delay) {
let timer = null;
return function () {
clearTimeout(timer);
timer = setTimeout(() => {
callback()
}, delay)
}
}
export default {
inserted(el, binding) {
/**
* handleClick(v-debounce="handleClick")
* value 就是上述中的 handleClick 方法
* <button v-debounce:2000="handleClick2s">防抖指令2s</button>
* arg 就是 2000 这里表示的是防抖间隔2000ms 默认是200ms
*/
const { value, arg = 200 } = binding;
el.addEventListener("click", handler(value, arg))
},
unbind(el) {
el.removeEventListener("click", handler)
}
}
// 注册自定义指令(debounce.js)
import debounce from "debounce.js";
Vue.directive("debounce", debounce);
// index.vue 中使用
<template>
<div>
<button v-debounce="handleClick">防抖指令</button>
<!-- :后面的就是附带的指令信息 可以在自定义指令中通过arg拿到 -->
<button v-debounce:2000="handleClick2s">防抖指令2s</button>
</div>
</template>
<script>
export default {
data() {
return {}
},
methods: {
handleClick() {
console.log("防抖默认 200ms")
},
handleClick2s() {
console.log("防抖2s");
}
}
}
</script>
例子-节流
// throttle.js 节流指令
function handler(callback, delay) {
let timer = null;
return function () {
if (timer) return
timer = setTimeout(() => {
callback();
clearTimeout(timer);
timer = null;
}, delay)
}
}
export default {
inserted(el, binding) {
// value 就是事件处理函数 即这个指令触发后会执行的函数体
const { value, arg, modifiers } = binding;
// 节流间隔时间 默认 200ms
let delay = arg ?? 200;
/**
* <input type="text" v-throttle.keyup="handleThrottle" />
* modifiers的值是一个对象 key是keyup 值是true 但是需要这个key
* 所以通过对象的方法Object.keys拿到这个对象的所有key再取第一个 拿来作为我们的事件类型
*/
let event = Object.keys(modifiers)[0];
el.addEventListener(event, handler(value, delay))
},
unbind(el) {
let event = Object.keys(modifiers)[0];
el.removeEventListener(event, handler);
}
}
// 注册自定义指令(throttle.js)
import debounce from "throttle.js";
Vue.directive("throttle", throttle);
// index.vue 中使用
<template>
<div>
<input type="text" v-throttle.keyup="handleThrottle" />
<button v-throttle:1000.click="handleThrottle1s">节流1s</button>
</div>
</template>
<script>
export default {
data() {
return {}
},
methods: {
handleThrottle1s() {
console.log("click节流1s");
},
handleThrottle() {
console.log("keyup节流触发");
}
}
}
</script>
当我们注册了多个全局指令时,我们需要一个一个的去引入再注册,这是非常麻烦的,所以我们可以将指令文件放在单独的一个文件夹中
然后我们在index.js中批量注册
// 批量注册自定义指令
import Vue from "vue";
const files = require.context("./modules", false, /\.js$/);
const names = files.keys();
for (const filename of names) {
const config = files(filename);
const name = filename.replace(/^\.\//, '').replace(/\.js$/, '');
Vue.directive(name, config.default || config)
}
然后在main.js中引入这个index.js文件即可
// main.js
import "@/directives/index";
这样就完成了全局指令的批量注册
局部指令注册
// index.vue 中
<template>
<div>
<input type="text" v-focus>
</div>
</template>
<script>
export default {
data() {
return {}
},
directives: {
focus: {
inserted(el) {
el.focus(); // 自动聚焦
}
}
}
}
</script>