文章目录
Vue中自定义指令🍤自定义指令介绍🍤自定义指令使用🍤指令的生命周期🍤指令参数和修饰符🍤自定义指令练习Vue中自定义指令
🍤自定义指令介绍
在Vue的模板语法中我们学习过各种各样的指令: v-show、 v-for、 v-model等等,除了使用这些指令之外, Vue也允许我们来自定义自己的指令。
注意:在Vue中,代码的复用和抽象主要还是通过组件;
通常在某些情况下,你需要
对DOM元素进行底层操作
,这个时候就会用到自定义指令
;
自定义指令分为两种:
自定义局部指令:组件中通过 directives 选项,只能在当前组件中使用;
自定义全局指令: app的 directive 方法,可以在任意组件中被使用;
比如我们来做一个非常简单的案例:当某个元素挂载完成后可以自定获取焦点
实现方式一:如果我们使用默认的实现方式;
实现方式二:自定义一个 v-focus 的局部指令;
实现方式三:自定义一个 v-focus 的全局指令;
接下来我们看看三种方式分别如何实现
🍤自定义指令使用
实现方式一:聚焦的默认实现
通过ref操作DOM获取到元素, 再对元素添加focus
但是这个方式有一个明显缺点, 当多个页面都需要此功能时, 我们多个页面都需要如下操作一遍, 会非常麻烦
<input type="text" ref="inputRef"><script setup>import {ref, onMounted } from "vue"const inputRef = ref()onMounted(() => {inputRef.value.focus()})</script>
实现方式二:自定义一个局部指令
例如我们自定义一个v-focus指令, 这个自定义指令实现非常简单,我们只需要在组件选项中使用
directives
即可;它是一个对象,在对象中编写我们自定义指令的名称(注意:这里不需要加v-);
自定义指令有一个生命周期,是在组件挂载后调用的 mounted,我们可以在其中完成操作;
当然, 自定义的局部指令只能在当前定义的组件中使用, 其他组件无法使用自定义指令
Options API 实现方式
<input type="text" v-focus><script>export default {directives: {focus: {// 自定义指令的生命周期函数, 当绑定的元素被挂载之后, 会执行, 并将该元素el传入mounted(el) {el.focus()}}}}</script>
Composition API 实现方式
<input type="text" v-focus><script setup>// 自定义指令const vFocus = {// 自定义指令的生命周期函数mounted(el) {el.focus()}}</script>
实现方式三:自定义全局指令
在开发中我们常用的是自定义全局指令, 自定义一个全局的指令可以让我们在任何地方直接使用
我们之前是在mian.js中注册的全局组件, 全局指令同样是在main.js中注册的
const app = createApp(App)app.directive("focus", {mounted(el) {el.focus()}})
🍤指令的生命周期
一个自定义指令定义的对象, Vue提供了如下的几个钩子函数:
created:元素已创建, 在绑定元素的 attribute 或事件监听器被应用之前调用;beforeMount:当指令第一次绑定到元素并且在挂载父组件之前调用;mounted:在绑定元素的父组件被挂载后调用;beforeUpdate:在更新包含组件的 VNode 之前调用, 绑定元素的内部或后代元素更新也会执行;updated:在包含组件的 VNode 及其子组件的 VNode 更新后调用;beforeUnmount:在卸载绑定元素的父组件之前调用;unmounted:当指令与元素解除绑定且父组件已卸载时,只调用一次;
const vMy = {created() {console.log("created")},beforeMount() {console.log("beforeMount")},mounted() {console.log("mounted")},beforeUpdate() {console.log("beforeUpdate")},updated() {console.log("updated")},beforeUnmount() {console.log("beforeUnmount")},unmounted() {console.log("unmounted")},}
🍤指令参数和修饰符
如果我们指令需要接受一些参数或者修饰符我们可以如下进行操作:
<h2 v-my:info.aaa.bbb="{name: chenyq, age: 18}">app</h2>
info是参数的名称;
aaa-bbb是修饰符的名称;
等于符号后面是传入的具体的值;
在我们的生命周期中,我们可以通过第二个参数bindings
获取到对应的内容:
bindings对应的是一个对象
对象中, arg存放的是参数, modifiers中存放的是修饰符, value中存放的是参数值
演示代码: 例如传入一个文本替换当前元素中的文本
<h2 v-my:info="message">app</h2><script setup>const message = "哈哈哈哈"const vMy = {mounted(el, bindings) {// 通过bindings获取到参数值el.textContent = bindings.value},}</script>
🍤自定义指令练习
自定义指令案例:时间戳的显示需求:
在开发中,大多数情况下从服务器获取到的都是时间戳;
我们需要将时间戳转换成具体格式化的时间来展示;
在Vue2中我们可以通过过滤器来完成;
在Vue3中我们可以通过 计算属性(computed) 或者 自定义一个方法(methods) 来完成;
其实我们还可以通过一个自定义的指令来完成;
我们来实现一个可以自动对时间格式化的指令v-format-time:
这里我使用的是自定义局部指令演示, 正常情况应该是自定义全局指令;
演示代码如下
<!-- 默认格式展示 --><h2 v-time>{{ timestamp }}</h2><!-- 自定义格式展示 --><h2 v-time="'YYYY/MM/DD'">{{ timestamp }}</h2><script setup>import dayjs from "dayjs"const timestamp = 1295658132const vTime = {mounted(el, bindings) {// 1.如果传入的是秒钟, 我们将其转为毫秒let timestamp = el.textContentif (timestamp.length === 10) {timestamp = timestamp * 1000}// 2.接收参数, 可以自定义时间的格式let value = bindings.valueif (!value) {value = "YYYY-MM-DD HH:mm:ss"}// 3.对时间进行格式化const formatTime = dayjs(timestamp).format(value)el.textContent = formatTime},}</script>