前言
最近在准备面试,于是狂刷面试题,深感前端内卷之深以及个人知识之浅薄,于是想着开一个个人专题来加深一下面试题的记忆,防止猪脑过载给忘光了
Vue指令是什么?
使用过Vue的开发者对自定义指令
这个词一定不会陌生,常用的v-bind
、v-show
等都属于自定义指令,都是在Vue
中默认注册的。
当Vue
的编译引擎在解析模板的时候,首先把DOM元素给解析成一个AST对象
,里面包含了为该元素绑定的指令
;然后将指令的钩子函数添加到vnode的回调函数中
;最后在执行createElm函数生成真实DOM
时根据vnode的回调队列
执行指令的内容。(详情看Vue指令实现原理)
自定义指令的钩子函数
胡乱分析一通,最后还是得靠手撕才能真的理解透彻。
想要创建一个自定义指令,首先需要了解以下两点(以下介绍为Vue3
版本):
自定义指令的钩子函数
正如上面分析中提到,Vue指令
其实是通过创建钩子函数来实现对DOM的操作的,指令的钩子函数有以下几个:
created
:绑定元素的 attributes 前
,和事件监听器调用前
被调用beforeMount
:绑定元素被插入到 DOM 前
被调用mounted
:绑定元素的父元素 和 绑定元素中的所有子元素 都挂载完成后
被调用beforeUpdate
:绑定元素的 父元素 更新前
被调用updated
:绑定元素的父元素 和 绑定元素的所有子元素 都更新完成后
被调用beforeUnmount
:绑定元素的父元素 被卸载前
被调用unmounted
:绑定元素的父元素 被卸载后
被调用
自定义指令钩子函数的参数
指令钩子函数的参数
有以下几个:
el
:指令绑定到的元素。这可以用于直接操作 DOM。binding
:一个对象,包括以下几个属性value
:传给指令的值,如v-if='true'
中,value为true
oldValue
:历史值,仅在beforeUpdate
和updated
中使用,无论值是否修改都可用arg
:传递给指令的参数,如在v-model:myValue
中,参数是'myValue'
modifiers
:一个包含修饰符的对象,如在v-my-directive.foo.bar
中,修饰对象为`{ foo: true, bar: true }instance
:使用该指令的组件实例dir
:指令的定义对象
vnode
:代表绑定元素的底层VNodeprevNode
:之前的渲染中代表指令所绑定的元素的VNode,仅在beforeUpdate
和updated
中可用
如何创建自定义指令
我想要达到的效果是通过自定义指令,达到点击一个纯文本DOM
就能复制内容的效果,要达到这个目的需要经过那些步骤呢?
1. 初始化自定义指令
想要开飞机,首先得有一辆飞机。那么下面我就在Vue3
中初始化一个自定义指令
// myDirective.js
const copy = {
mounted: el => console.log(el),
};
export default copy;
// main.js
import copy from "./assets/myDirective";
app.directive("copy", copy);
到这里,我们只需要在随意一个DOM元素上绑定v-copy
然后刷新页面,就会在控制台中看到输出了这个DOM元素,说明自定义指令已经初始完成
完善指令
接下来的步骤就很简单了,只需要在mounted钩子函数
中获取到DOM元素的文本内容,然后调用copy方法即可
// myDirective.js
const copy = {
mounted: el => {
const copy = () => {
if (!el.innerHTML) throw "无复制内容";
// 由于chrome默认设置的原因,可能会出现无法使用clipboard的情况
if (navigator.clipboard && window.isSecureContext) {
navigator.clipboard.writeText(el.innerHTML).then(() => {
console.log("复制成功");
});
} else {
const textarea = document.createElement("textarea");
textarea.readOnly = "readonly";
textarea.style.position = "absolute";
textarea.style.left = "-99999px";
// 赋值
textarea.value = el.innerHTML;
document.body.appendChild(textarea);
textarea.select();
const result = document.execCommand("copy");
if (result) console.log("复制成功");
document.body.removeChild(textarea);
}
};
el.addEventListener("click", copy);
},
};
效果👇
大功告成~
结语
没啥结语~
要是文中有任何错误或者需要修改的内容,烦请指出,希望我这个小菜鸡的个人理解不会误人子弟~