在 Vue 中,指令是直接编辑 DOM 的最佳方式之一。
一些示例包括 、 、 等。如果你在 Vue 工作过,你就会熟悉指令:v-if,``v-show,``v-bind。
正如你可能猜到的那样,Vue 自定义指令是 Vue 让我们为我们的项目构建额外指令的方式。它们是在整个项目中添加独特且可重用功能的好方法。
Vue 自定义指令可以操作元素以及处理 DOM 中的反应性。
在本中级教程结束时,您将了解:
-
什么是自定义指令
-
Vue 指令的各种事件钩子
-
如何创建自定义指令
现在是自定义指令时间!
什么是自定义指令 {#what-is-a-custom-directive}
从本质上讲,自定义指令是使您的项目符合您的需求的一种方式。如果你使用 Vue 插件,你会注意到它们非常频繁地使用自定义指令。
例如,在v-lazy 插件,他们使用指令 v-lazy 来添加自定义功能,使图像加载更有效。在这里使用指令是最好的情况,因为我们想直接编辑 DOM。
你可能会问,"我不能只注册计算和观察程序等组件选项吗?"
是的。您可以。但是,虽然组件选项对于抽象和代码重用很有用,自定义指令仍然是最好的方法之一直接操作 DOM 元素。
但是,虽然组件选项对于抽象和代码重用很有用,自定义指令仍然是最好的方法之一直接操作 DOM 元素。
指令有五个钩子 {#a-directive-has-five-hooks}
就像组件及其生命周期钩子一样,每个 Vue 指令都有自己的钩子来触发
Vue 2 和 Vue 3 中的指令钩子是不同的。
以下是 Vue 2 指令钩子:
-
bind
-- 当指令绑定到元素时调用一次 -
inserted
-- 当绑定元素插入其父节点时 -
update
-- 当元素更新时(但任何子项尚未更新) -
componentUpdated
-- 在孩子们也更新之后 -
unbind
-- 当指令与元素解除绑定时调用一次
以下是 Vue 3 指令钩子:
-
created
-- 在应用元素的属性或事件侦听器之前调用。 -
beforeMount
-- 与旧的绑定钩子相同 -
mounted
-- 与旧的插入钩子相同 -
beforeUpdate
-- 在元素本身更新之前调用(如生命周期钩子) -
updated
-- 与旧组件相同更新的钩子 -
beforeUnmount
-- 在卸载元素之前调用(如生命周期钩子) -
unmounted
-- 与旧的 Unbind Hook 相同
在实现这些钩子时,它们各自都有一些它们接受的参数。
-
el
-- 指令绑定到此元素;允许您修改它 -
binding
-- 一个对象包含很多属性;我们稍后将深入探讨 -
vnode
-- 虚拟节点 -
prevVnode
-- 上一个虚拟节点(仅在更新钩子中可用)
重要说明Vue 指令文档是您应该将这些参数(除了 EL)视为只读,并且永远不要修改它们。
绑定对象 {#the-binding-object}
绑定对象包含多个属性,可帮助您实际向钩子添加功能。
-
name
-- 指令名称(无前缀)v-
-
value
-- 传递给指令的值 -
oldvalue
-- 指令的上一个值(仅在更新钩子中可用) -
expression
-- 绑定到字符串的表达式(例如,expression =v-direc="3 * 3″``"3*3"
) -
arg
-- 传递给字符串的任何参数(例如 V-direc:blue,arg = blue) -
modifiers
-- 所有作为对象传递的修饰符(例如 V-direc.blue.link,修饰符 = {blue: true, link: true}
定义指令 {#defining-your-directive}
在我们的文件中------或者无论你的 Vue 实例在哪里------我们只需要使用 Vue 2 中的方法或 Vue 3 中的方法。main.js``Vue.directive``app.directive
现在,让我们创建一个指令,允许我们操作组件的字体大小。它将被称为v-font-size。
在里面,我们将添加一些代码来监听 and 钩子并调整字体大小。main.js``beforeMount``updated
// Vue 2
Vue.directive("font-size", {
bind: (el, binding) => {
el.style.fontSize = 24 + "px";
},
updated: (el, binding) => {
el.style.fontSize = 24 + "px";
},
});
// Vue 3
app.directive("font-size", {
beforeMount: (el, binding) => {
el.style.fontSize = 20 + "px";
},
updated: (el, binding) => {
el.style.fontSize = 20 + "px";
},
});
从现在开始,我将使用 Vue 3 实现钩子,但如果需要,您可以将它们映射到上面的 Vue 2 钩子。
然后,在任何组件文件中,让我们添加以下两行,以便我们可以看到我们的组件的运行情况!每当我们声明一个指令时,我们都可以使用前缀 .v-
<p>Default Font Size</p>
<p v-font-size>Modified Font Size</p>
还有另一种方法可以定义你的 Vue 指令。作为速记,您也可以在里面使用这种语法main.js
// pass a function!
app.directive("font-size", (el, binding) => {
el.style.fontSize = 24 + "px";
});
如果传递的是函数而不是对象,则它将在绑定和更新钩子期间运行。
我们有我们的第一个自定义指令在工作!现在,让我们把它做得更高级一些。
将参数传递给指令 {#passing-arguments-to-your-directive}
有几种方法可以增加对指令的更多控制。这可以通过传递其他值、参数或修饰符来完成
在我们的示例中,假设我们希望更好地控制元素中的字体大小。
传递的值 -- 用于反应式数据 {#passed-values-for-reactive-data}
传递数据最直观的方法是简单地为其提供一个值。这允许您的指令在值更改时响应式更新。这也提供了最灵活的控制,因为您可以接受各种值(任何字体大小)。
在您的组件中,声明将如下所示...
<p v-font-size='12'>Uses font-size directive</p>
<!-- OR USE A VARIABLE -->
<p v-font-size='fontSize'>Uses font-size directive</p>
在指令中,您需要更改方法以使用对象中的值。binding
app.directive('font-size', (el, binding, vnode) => {
el.style.fontSize = binding.value + 'px'
})
向指令发送参数 {#sending-arguments-to-directives}
如果您真的不需要任何反应性,只是想要一种方法来为您的指令提供多个选项。争论是做到这一点的好方法。
指令中的代码是这样的。
app.directive('font-size', (el, binding, vnode) => {
console.log(binding + ' ' + vnode)
var size = 16
switch (binding.arg) {
case 'small':
size = 8
break
case 'large':
size = 32
break
default:
size = 16
break
}
el.style.fontSize = size + 'px'
})
然后在我们的模板中。
<p v-font-size:small>Small</p>
<p v-font-size:medium>Medium</p>
<p v-font-size:large>Large</p>
使用修饰符 {#using-modifiers}
修饰符与参数相似,因为它们不适合反应性。但是当与参数结合使用时,您可以创建一个非常自定义的系统。
这是因为您可以在一个指令上应用多个修饰符。
让我们先在我们的指令中实现它们。和 的顺序仅取决于要优先处理哪些修饰符。if``else-if
Vue.directive("font-size", (el, binding, vnode) => {
console.log(binding + " " + vnode);
var defaultSize;
if (binding.modifiers.small) {
defaultSize = 12;
} else if (binding.modifiers.large) {
defaultSize = 32;
} else {
defaultSize = 16;
}
if (binding.modifiers.red) {
el.style.color = "#ff0000";
}
el.style.fontSize = defaultSize + "px";
});
然后我们可以在模板中使用它们
<p v-font-size.small.red>Small</p>
<p v-font-size.medium>Medium</p>
<p v-font-size.large>Large</p>
结论 {#conclusion}
恭喜!
你已经做到了这里,现在应该有一些注册你的 Vue 自定义指令的工作知识。
感谢您的关注,我希望本文为您提供构建一些出色工具所需的工具。
祝您编码愉快!