一、认识自定义指令
目录
一、认识自定义指令
方式一、使用默认实现方式,使用 ref 实现,并抽取到 hooks,方便调用。
方式二、自定义一个 v-focus 的局部指令
方式三:自定义一个 v-focus 的全局指令
- 某些情况,你需要对 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>