一、认识自定义指令
目录
方式一、使用默认实现方式,使用 ref 实现,并抽取到 hooks,方便调用。
- 某些情况,你需要对 DOM 元素进行底层操作,此时会用到自定义指令。
- 自定义指令分为两种:
- 自定义局部指令
- 组件中通过 directives 选项,只能在当前组件中使用;
- 自定义全局指令
- app 的 directive方法,可以在任意组件中被使用
- 比如做一个简单的案例:当某个元素挂载完成后可以自定获取焦点
- 实现方式一:使用默认实现方式
- 实现方式二:自定义一个 v-focus 的局部指令
- 实现方式三:自定义一个 v-focus 的全局指令
方式一、使用默认实现方式,使用 ref 实现,并抽取到 hooks,方便调用。
<!-- App.vue -->
<template>
<div class="app">
<input type="text" ref="inputRef" />
</div>
</template>
<script setup>
// 1.方法一:定义 ref 绑定到 input 中,调用 focus()
import useInput from './hooks/useInput'
const { inputRef } = useInput()
</script>
<style scoped lang="less"></style>
新建 hooks/useInput.js
import { ref, onMounted } from 'vue'
export default function useInput() {
const inputRef = ref()
onMounted(() => {
inputRef.value?.focus()
})
return { inputRef }
}
方式二、自定义一个 v-focus 的局部指令
缺点:只能在局部使用,不能复用。
注意:需要定义一个标识符 v 开头
<!-- App.vue -->
<template>
<div class="app">
<!-- 方式二、自定义指令 -->
<input type="text" v-focus />
</div>
</template>
<!-- <script>
export default {
directives: {
focus: {
// focus: {} 这个对象里放的是生命周期的函数(自定义指令),会把元素 el 传过来
mounted(el) {
// 当v-focus应用到 input上,input被挂载到DOM上后,就会回调 mounted 生命周期函数
console.log('v-focus 应用到元素被挂载了', el)
el?.focus()
}
}
}
}
</script> -->
<script setup>
// 2.方式二:自定义指令(局部指令)
// 注意:定一个标识符,v开头
const vFocus = {
mounted(el) {
// 当v-focus应用到 input上,input被挂载到DOM上后,就会回调 mounted 生命周期函数,
console.log('v-focus 应用到元素被挂载了', el)
el?.focus()
}
}
</script>
<style scoped lang="less"></style>
方式三:自定义一个 v-focus 的全局指令
- 为方便复用,写在 main.js 里
import { createApp } from 'vue'
import App from './01_自定义指令/App.vue'
const app = createApp(App)
// 自定义全局指令,需要定义个名称
app.directive('focus', {
mounted(el) {
// 当v-focus应用到 input上,input被挂载到DOM上后,就会回调 mounted 生命周期函数,
console.log('v-focus 应用到元素被挂载了', el)
el?.focus()
}
})
app.mount('#app')
- 但是有时候自定义指令会有很多,所以可以单独抽取出来,新建文件夹 directives
1. 先抽取到 focus.js 里
export default function directiveFocus(app) {
// 自定义全局指令,需要定义个名称
app.directive('focus', {
mounted(el) {
// 当v-focus应用到 input上,input被挂载到DOM上后,就会回调 mounted 生命周期函数,
console.log('v-focus 应用到元素被挂载了', el)
el?.focus()
}
})
}
2.新建一个index.js
- 在这里导出所有的自定义指令,方便直接在mian.js中使用
import directiveFocus from './focus'
export default function useDirectives(app) {
directiveFocus(app)
}
3.main.js
import { createApp } from 'vue'
import App from './01_自定义指令/App.vue'
import useDirectives from './01_自定义指令/directives/index'
const app = createApp(App)
// 自定义指令
useDirectives(app)
app.mount('#app')
二、生命周期-自定义指令的生命周期
一个指令定义到对象,vue提供了如下的几个钩子函数:
- created:在绑定元素的 attribute 或事件监听器被应用之前调用;
- beforeMount:当指令第一次绑定到元素并且在挂载父组件之前调用;
- mounted:在绑定元素的父组件被挂载后调用;
- beforeUpdate:在更新包含组件的 VNode 之前调用;
- updated:在包含组件的 VNode 及其子组件的 VNode 更新后调用;
- beforeUnmount:在卸载绑定元素的父组件之前调用;
- unmounted: 当指令与元素解除绑定并且父组件已卸载时,只调用一次;
<template>
<div class="app">
<div class="title" v-if="showTitle" v-why>当前计数{{ counter }}</div>
<button @click="counter++">+1</button>
<button @click="showTitle = false">隐藏</button>
</div>
</template>
<script setup>
import { ref, reactive, onMounted } from 'vue'
const counter = ref(0)
const showTitle = ref(true)
const vWhy = {
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')
}
}
</script>
<style scoped></style>