Vue3 - 自定义指令封装

Vue3 - 自定义指令封装

  • 一. 自定义指令封装
    • 1.1 全局/局部注册自定义聚焦指令
    • 1.2 自定义指令相关参数
    • 1.3 自定义指令参数传递
  • 二. 总结

一. 自定义指令封装

vue中有很多内置的指令,我们一般在开发中也经常用到,比如v-if,v-for等等。那么本篇文章就来讲一讲如何自定义指令。

我们先来看下一个简单的功能,我们画一个简单的页面,然后页面里面有一个文本框:

<template>
  <div class="border">
    <h1 >我是父组件</h1>
    文本框:<inpu type="text">
  </div>
</template>
<script setup>

</script>

<style scoped>
.border {
  border: 1px solid;
  width: 400px;
  height: 200px;
}
</style>

运行结果如下:
Vue3 - 自定义指令封装_第1张图片
那么如果我希望页面刚进入,就能聚焦到这个文本框中,该怎么做?我们这里就使用自定义指令的功能来完成。

1.1 全局/局部注册自定义聚焦指令

首先我们说下局部的定义方式,我们在首页中添加以下代码:

<script setup>
const vFocus = {
  mounted: (el) => {
    console.log('mounted');
    el.focus();
  },
};
</script>

然后再inpu标签上添加指令:,那么页面刷新一下,效果如下:可见已经聚焦到文本框中,并且输出了对应的内容。
Vue3 - 自定义指令封装_第2张图片

紧接着再来说下全局的注册,主要在main.ts入口文件中使用directive函数进行注册。这样任何一个组件中都可以使用指令:v-focus

import { createApp } from 'vue'
import './style.css'
import App from './App.vue'

createApp(App)
    .directive('focus', {  
        // 当被绑定的元素挂载到 DOM 中时
        mounted(el) {    
            // 聚焦元素    
            el.focus()
        }
    })
    .mount('#app')

讲到这里,其实我并没有对指令的定义做出太多的解释,先把这个功能代码贴出来,接下来开始细讲。

1.2 自定义指令相关参数

大家可以从案例中看到,在定义自定义指令的时候,我们定义了一个mounted函数,其实除了他还有几个钩子函数。

  • created:在绑定元素的 attribute 前或事件监听器应用前调用。
  • beforeMount:当指令第一次绑定到元素上并且在父组件被挂载前调用。
  • mounted:在绑定元素的父组件及他自己的所有子节点都挂载完成后调用,一般我们自定义指令的逻辑都写在这里。
  • beforeUpdate:绑定元素的父组件及他自己的所有子节点都更新前调用。
  • updated:在绑定元素的父组件及他自己的所有子节点都更新后调用。
  • beforeUnmount:在父组件被卸载前调用。
  • unmounted:当指令和元素已经解除绑定并且父组件也已经被卸载的时候调用。

同样,我们还注意到,我们定义mounted钩子函数的时候,还传入了一个参数el,除此之外,还有三个参数,一共4个。

  • el(读写):指令所绑定的元素,可以直接操作DOM
  • binding(只读):通过自定义指令传递的参数都在这里。
  • vnode(只读):Vue编译生成的虚拟节点。
  • oldVnode(只读):上一个虚拟节点,仅仅在updatecomponentUpdated钩子函数中才可以使用。

1.3 自定义指令参数传递

我们来看下这个案例:

<template>
  <div class="border">
    <h2>我是父组件</h2>
    <button v-onceClick:{name:myName,age:10}="1">按钮1</button>
    <br>
    <button v-onceClick:{name:myName,age:10}="3">按钮3</button>
  </div>
</template>
<script setup>
const myName = "ljj";

const vOnceClick = {
  mounted: (el, binding, vnode) => {
    el.addEventListener("click", () => {
      if (!el.disabled) {
        el.disabled = true;
        let time = binding.value * 1000;
        setTimeout(() => {
          el.disabled = false;
        }, time);
      }
      console.log(binding.value,binding.arg)
    });
    console.log(vnode)
  },
};
</script>

<style scoped>
.border {
  border: 1px solid;
  width: 400px;
  height: 200px;
}
</style>

效果如下:
Vue3 - 自定义指令封装_第3张图片
我们可以看到,首先打印的是Vue编译后的虚拟节点相关信息。之后基本上同时点击了两个按钮。一个置灰了1秒,一个置灰了3秒。符合代码编写。

我们把这段代码拆分开来说:v-onceClick:{name:myName,age:10}="3"

  • 冒号后面的是引入的值:{name:myName,age:10}这块部分,竟然是一个字符串,我们代码里面定义了myName变量,值是ljj。但是从输出结果来看,他并不是我们期望的。但是我们可以从binding.arg中拿到这个值。
  • 我们可以从binding.value中拿到="3"这部分的数据。

后来经过我的测验,针对第一点,我们这样改,传入一个单对象,使用中括号:

<button v-onceClick:[{name:myName,age:10}]="1">按钮1</button>
<br />
<button v-onceClick:[myName]="3">按钮3</button>

结果如下:
Vue3 - 自定义指令封装_第4张图片

二. 总结

总结下自定义指令的封装相关知识点:

  • 自定义指令,我们一般需要定义一个对象,里面包含一个mounted函数,我们主要在这个函数中,对传入的el参数,操作DOM节点。编写自己的业务逻辑即可。
  • 如果希望往指令函数中传入相关的参数,可以通过 v-指令名称:[Obj]=val的写法来完成。
  • Obj则由mounted这样钩子函数的第二个参数binding对象中获得,即biding.arg
  • val则通过biding.value来获得。
  • 注意相关钩子函数中,一般我们只操作第一个参数el来控制DOM节点,其他参数一般是只读的。
  • 一般我们命名自定义指令 const v指令名称 = {}Vue3写法中v前缀一定要有,使用的时候则由 v-指令名称来指定。首字母大小写不影响。例如定义指令函数:vFocus,那么使用的时候v-focus或者v-Focus都可。

你可能感兴趣的:(Vue,vue.js,javascript,前端)