自定义指令
介绍
内置指令(v-model等)
自定义指令主要是为了重用涉及普通元素的底层 DOM 访问的逻辑。
一个自定义指令由一个包含类似组件生命周期钩子的对象来定义。钩子函数会接收到指令所绑定元素作为其参数。
一个指令的定义对象可以提供几种钩子函数 (都是可选的):
import type { Directive, DirectiveBinding } from "vue";
const myDirective : Directive = {
// 在绑定元素的 attribute 前
// 或事件监听器应用前调用
created(el:HTMLElement, binding:DirectiveBinding, vnode, prevVnode) {
// 下面会介绍各个参数的细节
},
// 在元素被插入到 DOM 前调用
beforeMount(el, binding:DirectiveBinding, vnode, prevVnode) {},
// 在绑定元素的父组件
// 及他自己的所有子节点都挂载完成后调用
mounted(el, binding:DirectiveBinding, vnode, prevVnode) {},
// 绑定元素的父组件更新前调用
beforeUpdate(el, binding:DirectiveBinding, vnode, prevVnode) {},
// 在绑定元素的父组件
// 及他自己的所有子节点都更新后调用
updated(el, binding:DirectiveBinding, vnode, prevVnode) {},
// 绑定元素的父组件卸载前调用
beforeUnmount(el, binding:DirectiveBinding, vnode, prevVnode) {},
// 绑定元素的父组件卸载后调用
unmounted(el, binding:DirectiveBinding, vnode, prevVnode) {}
}
钩子参数
指令的钩子会传递以下几种参数:
-
el
:指令绑定到的元素。这可以用于直接操作 DOM。 -
binding
:一个对象,包含以下属性。value
:传递给指令的值。例如在v-my-directive="1 + 1"
中,值是2
。oldValue
:之前的值,仅在beforeUpdate
和updated
中可用。无论值是否更改,它都可用。arg
:传递给指令的参数 (如果有的话)。例如在v-my-directive:foo
中,参数是"foo"
。modifiers
:一个包含修饰符的对象 (如果有的话)。例如在v-my-directive.foo.bar
中,修饰符对象是{ foo: true, bar: true }
。instance
:使用该指令的组件实例。dir
:指令的定义对象。
-
vnode
:代表绑定元素的底层 VNode。 -
prevNode
:之前的渲染中代表指令所绑定元素的 VNode。仅在beforeUpdate
和updated
钩子中可用。
插件全局注册指令使用
插件 (Plugins) 是一种能为 Vue 添加全局功能的工具代码。
import type { App, Plugin } from "vue";
import copy from "./modules/cope";//复制指令模板
const directivesList: any = {
copy
};
// 插件注册全局自定义指令
const directives: Plugin = {
install: (app: App) => {
Object.keys(directivesList).forEach(key => {
app.directive(key, directivesList[key]);
});
}
};
export default directives;
//main.ts 使用插件
app.use(directives)
常用指令
v-cope 复制粘贴指令
import type { Directive, DirectiveBinding } from "vue";
import { ElMessage } from "element-plus";
interface ElType extends HTMLElement {
copyData: string | number;
}
const copy: Directive = {
// 在绑定元素的父组件
// 及他自己的所有子节点都挂载完成后调用
mounted(el: ElType, binding: DirectiveBinding) {
el.copyData = binding.value;// v-cope="value"传进来的值
el.addEventListener("click", handleClick);
},
updated(el: ElType, binding: DirectiveBinding) {
el.copyData = binding.value;// 值改变重新赋值
},
// 绑定元素的父组件卸载前调用
beforeUnmount(el: ElType) {
el.removeEventListener("click", handleClick);
}
};
function handleClick(this: any) {
let copyFont = this.copyData.toLocaleString();
let textFont = null;
// 仿知乎掘金 复制一两个字则不添加版权信息 超过一定长度的文字 就添加版权信息
if (copyFont.length > 10) {
textFont = `
${copyFont}
--------------------------------三八线--------------------------------
联系方式:QQ825437313
外貌:10不存1,187cm是吧?200斤?减肥计划开始!!
来源: 爱会凋零,花会枯萎!
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。`;
} else {
textFont = copyFont; // 没超过十个字 则采用被复制的内容。
}
navigator.clipboard.writeText(textFont)//复制粘贴
.then(() => {
ElMessage({
type: "success",
message: "复制成功"
});
})
.catch(() => {
ElMessage({
type: "error",
message: "复制失败"
});
});
}
export default copy;
// 使用 <el-button v-copy="copeData">点击复制</el-button>
const copeData = ref<string>("我是被复制的内容 🍒 🍉 🍊");