Vue3 學(xué)習(xí)筆記 —Vue3 自定義指令
自定義指令分為全局和局部?jī)煞N類(lèi)型,大家并不陌生。今天我們就講講在 vue3 中,自定義指令定義、使用以及鉤子函數(shù)都有哪些變化?
一、注冊(cè)自定義指令
以下實(shí)例都是實(shí)現(xiàn)一個(gè)輸入框自動(dòng)獲取焦點(diǎn)的自定義指令。
1.1、全局自定義指令
在vue2中,全局自定義指令通過(guò) directive 掛載到 Vue 對(duì)象上,使用 Vue.directive('name',opt)。
實(shí)例1:Vue2 全局自定義指令
- Vue.directive('focus',{
- inserted:(el)=>{
- el.focus()
- }
- })
inserted 是鉤子函數(shù),在綁定元素插入父節(jié)點(diǎn)時(shí)執(zhí)行。
在 vue3 中,vue 實(shí)例通過(guò)createApp 創(chuàng)建,所以全局自定義指令的掛載方式也改變了, directive 被掛載到 app上。
實(shí)例2:Vue3 全局自定義指令
- //全局自定義指令
- app.directive('focus',{
- mounted(el){
- el.focus()
- }
- })
- //組件使用
- <input type="text" v-focus />
1.2、局部自定義指令
在組件內(nèi)部,使用 directives 引入的叫做局部自定義指令。Vue2 和 Vue3 的自定義指令引入是一模一樣的。
實(shí)例3:局部自定義指令
- <script>
- //局部自定義指令
- const defineDir = {
- focus:{
- mounted(el){
- el.focus()
- }
- }
- }
- export default {
- directives:defineDir,
- setup(){}
- }
- </script>
二、自定義指令中的生命周期鉤子函數(shù)
一個(gè)指令定義對(duì)象可以提供如下幾個(gè)鉤子函數(shù)(都是可選的,根據(jù)需要引入)
- created :綁定元素屬性或事件監(jiān)聽(tīng)器被應(yīng)用之前調(diào)用。該指令需要附加需要在普通的 v-on 事件監(jiān)聽(tīng)器前調(diào)用的事件監(jiān)聽(tīng)器時(shí),這很有用。
- beforeMounted :當(dāng)指令第一次綁定到元素并且在掛載父組件之前執(zhí)行。
- mounted :綁定元素的父組件被掛載之后調(diào)用。
- beforeUpdate :在更新包含組件的 VNode 之前調(diào)用。
- updated :在包含組件的 VNode 及其子組件的 VNode 更新后調(diào)用。
- beforeUnmounted :在卸載綁定元素的父組件之前調(diào)用
- unmounted :當(dāng)指令與元素解除綁定且父組件已卸載時(shí),只調(diào)用一次。
實(shí)例3:測(cè)試指令內(nèi)生命周期函數(shù)執(zhí)行
- <template>
- <div>
- <input type="text" v-focus v-if="show"><br>
- <button @click="changStatus">{{show?'隱藏':'顯示'}}</button>
- </div>
- </template>
- //局部自定義指令
- const autoFocus = {
- focus:{
- created(){
- console.log('created');
- },
- beforeMount(){
- console.log('beforeMount');
- },
- mounted(el){
- console.log('mounted');
- },
- beforeUpdated(){
- console.log('beforeUpdated')
- },
- updated(){
- console.log('updated');
- },
- beforeUnmount(){
- console.log('beforeUnmount');
- },
- unmounted(){
- console.log('unmounted');
- }
- },
- }
- import { ref } from 'vue'
- export default {
- directives:autoFocus,
- setup(){
- const show = ref(true)
- return {
- show,
- changStatus(){
- show.value = !show.value
- }
- }
- }
- }
通過(guò)點(diǎn)擊按鈕,我們發(fā)現(xiàn)創(chuàng)建 input 元素的時(shí)候,會(huì)觸發(fā) created、beforeMount 和 mounted 三個(gè)鉤子函數(shù)。
隱藏 input 元素的時(shí)候,會(huì)觸發(fā) beforeUnmount 和 unmounted 。
然而我們添加的 beforeUpdate 和 updated 函數(shù)并沒(méi)有執(zhí)行。
此時(shí)我們把 input 元素上的 v-if 修改成 v-show 就會(huì)執(zhí)行上述兩個(gè)方法了,具體的執(zhí)行情況自行驗(yàn)證下。
從 vue2 升級(jí)到 vue3 ,自定義指令的生命周期鉤子函數(shù)發(fā)生了改變,具體變化如下:
- bind 函數(shù)被替換成了beforeMounted。
- update 被移除。
- componentUpdated 被替換成了updated。
- unbind 被替換成了 unmounted。
- inserted 被移除。
三、自定義指令鉤子函數(shù)的參數(shù)
鉤子函數(shù)被賦予了以下參數(shù):
- el:指令所綁定的元素,可以直接操作DOM。
- binding:是一個(gè)對(duì)象,包含該指令的所有信息。
binding 包含的屬性具體的分別為:
- arg 自定義指令的參數(shù)名。
- value 自定義指令綁定的值。
- oldValue 指令綁定的前一個(gè)值。
- dir 被執(zhí)行的鉤子函數(shù)
- modifiers:一個(gè)包含修飾符的對(duì)象。
- <template>
- <div>
- <div v-fixed >定位</div>
- </div>
- </template>
- <script>
- //自定義指令動(dòng)態(tài)參數(shù)
- const autoFocus = {
- fixed:{
- beforeMount(el,binding){
- console.log('el',el)
- console.log('binding',binding)
- }
- }
- }
- export default {
- directives:autoFocus,
- setup(){
- }
- }
- </script>
四、自定義指令參數(shù)
自定義指令的也可以帶參數(shù),參數(shù)可以是動(dòng)態(tài)的,參數(shù)可以根據(jù)組件實(shí)例數(shù)據(jù)進(jìn)行實(shí)時(shí)更新。
實(shí)例4:自定義指令動(dòng)態(tài)參數(shù)
- <template>
- <div>
- <div v-fixed:pos="posData" style="width:100px;height:100px;background:grey">定位</div>
- </div>
- </template>
- <script>
- //自定義指令動(dòng)態(tài)參數(shù)
- const autoFocus = {
- fixed:{
- beforeMount(el,binding){
- el.style.position = "fixed"
- el.style.left = binding.value.left+'px'
- el.style.top = binding.value.top + 'px'
- }
- }
- }
- export default {
- directives:autoFocus,
- setup(){
- const posData = {
- left:20,
- top:200
- }
- return {
- posData,
- }
- }
- }
- </script>
什么時(shí)候需要自定義指令?
- 需要對(duì)普通 DOM 元素進(jìn)行底層操作,這時(shí)候就會(huì)用到自定義指令。
- 需要將某些功能在指定DOM元素上使用,但對(duì)于需要操作大量DOM元素或者大變動(dòng)時(shí)候,推薦使用組件,而不是指令。