1.vue2的自定义指令
Vue
在除了提供默认内置的指令外,还允许开发人员根据实际情况自定义指令.
在Vue的项目中,大多数情况下,你都可以操作数据来修改视图,也就是所谓的操作DOM,但是还是避免不了偶尔要操作原生DOM,当我们需要操作DOM的时候,就可以使用到自定义指令。
当然也能用 $refs
,实现页面的输入框自动聚焦:
<template>
<input ref="input" />
</template>
<script>
export default {
mounted() {
this.$refs.input.focus();
}
}
</script>
代码基本能实现我们需要的功能,但是如果有很多页面都需要这个功能,那我们就只能是复制这段代码了,而通过自定义指令我们就能解决这种问题。
使用指令来实现:
Vue.directive('focus', {
bind() {},
inserted(el) {
el.focus()
},
update() {},
componentUpdated() {},
unbind() {}
})
我们通过全局Vue实例注册一个自定义指令,然后通过 v-focus
绑定到需要聚焦的 input 元素上。如果其他组件或模块也需要聚焦功能,只要简单的绑定此指令即可。
<template>
<input v-focus />
</template>
自定义指令能给我们带来很大的便利,在 Vue2
中给一个指令定义对象可以提供 bind
、inserted
、update
、componentUpdated
、unbind
五个钩子函数。
什么时候需要自定义指令?
- 需要对普通 DOM 元素进行底层操作,这时候就会用到自定义指令。
- 需要将某些功能在指定DOM元素上使用,但对于需要操作大量DOM元素或者大变动时候,推荐使用组件,而不是指令。
但是在新发布的 Vue3
中对指令也做了一些改造.
2.Vue3中的指令
bind => beforeMount
inserted => mounted
beforeUpdate: 新的钩子,会在元素自身更新前触发
update => 移除!
componentUpdated => updated
beforeUnmount: 新的钩子,当元素自身被卸载前触发
unbind => unmounted
在vue3中指令定义对象可以提供如下几个钩子函数(按需引入):
-
created :绑定元素属性或事件监听器被应用之前调用。该指令需要附加需要在普通的 v-on 事件监听器前调用的事件监听器时,这很有用。
-
beforeMounted :当指令第一次绑定到元素并且在挂载父组件之前执行。
-
mounted :绑定元素的父组件被挂载之后调用。
-
beforeUpdate :在更新包含组件的 VNode 之前调用。
-
updated :在包含组件的 VNode 及其子组件的 VNode 更新后调用。
-
beforeUnmounted :在卸载绑定元素的父组件之前调用
-
unmounted :当指令与元素解除绑定且父组件已卸载时,只调用一次。
Vue3 | Vue2 |
---|---|
created | |
beforeMount | bind |
mounted | inserted |
beforeUpdate | update |
updated | componentUpdated |
beforeUnmount | |
unmounted | unbind |
vue3改造后的生命周期钩子变成了七个,而且名称变得比较好记了
2.1全局的自定义指令
在 vue3 中,vue 实例通过createApp 创建,所以全局自定义指令的挂载方式也改变了, directive 被挂载到 app上。
例如定义一个指令改指定元素的颜色.
import { createApp } from 'vue'
import App from './App.vue'
var app = createApp(App)
app.directive("fouce", {
created(el, binding) {
console.log(el, binding);
el.style.color = binding.value;
},
updated(el, binding) {
el.style.color = binding.value;
}
})
app.mount('#app');
在组件中直接使用:
<template>
<h3 v-colos="'red'">自定义全局指令</h3>
</template>
除了直接在man.js中书写之外还可以外部引用:
实现格式化时间的指令:
创建dayTime.js
import dayjs from 'dayjs'
export default function (app) {
app.directive('focus', {
mounted(el) {
el.focus()
}
})
app.directive('format-time', {
mounted(el, binding) {
//console.log(binding.value);
const time = el.textContent * 1
el.textContent = dayjs(time).format(binding.value || 'YYYY-MM-DD HH:mm:ss')
}
})
}
在main.js中引入
import timeFormat from "./utils/dayTime"
var app = createApp(App)
timeFormat(app);
在组件中使用:
<input type="text" v-focus>
<h3 v-format-time="'YYYY-MM-DD hh:mm:ss'">1648626494687</h3>
2.2自定义指令钩子函数的参数
钩子函数被赋予了以下参数:
- el:指令所绑定的元素,可以直接操作DOM。
- binding:是一个对象,包含该指令的所有信息。
binding 包含的属性具体的分别为:
- arg 自定义指令的参数名。
- value 自定义指令绑定的值。
- oldValue 指令绑定的前一个值。
- dir 被执行的钩子函数
- modifiers:一个包含修饰符的对象。
2.3自定义指令参数
自定义指令的也可以带参数,参数可以是动态的,参数可以根据组件实例数据进行实时更新。
例如:根据用户传入的指令参数实现当前的定位
//man.js:
app.directive("locations", {
created(el, binding) {
el.style.position = "relative";
el.style[binding.arg] = binding.value + "px";
}
})
//组件:
<template lang="">
<div>
<h3 v-colos="'red'">全局自定义指令</h3>
<span v-locations:left="200">全局自定义指令:实现距离左侧200px</span>
<p v-locations:top="300" v-colos="'purple'" >全局自定义指令:实现距离顶部300px</p>
</div>
</template>
2.4局部指令
普通js中使用
<script>
export default {
directives:{
autoFocus: {
mounted(el) {
el.focus()
}
}
},
setup(props) {
}
}
</script>
setup语法糖中使用:
// 注册一个局部的自定义指令,需要以小写v开头
const vFocuss = {
mounted(el) {
// 获取input,并调用其focus()方法
el.focus()
}
}
//组件
<input type="text" v-focuss>