广告
返回顶部
首页 > 资讯 > 精选 >怎么在Vue3中实现自定义指令
  • 768
分享到

怎么在Vue3中实现自定义指令

2023-07-02 08:07:34 768人浏览 八月长安
摘要

这篇文章主要介绍“怎么在vue3中实现自定义指令”,在日常操作中,相信很多人在怎么在Vue3中实现自定义指令问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”怎么在Vue3中实现自定义指令”的疑惑有所帮助!接下来

这篇文章主要介绍“怎么在vue3中实现自定义指令”,在日常操作中,相信很多人在怎么在Vue3中实现自定义指令问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”怎么在Vue3中实现自定义指令”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

前言

我们需要明白为什么需要自定义一个指令,其实就是想更加简洁地重复使用操作DOM的逻辑,这就和组件化和组合式函数差不多。

不管是Vue内置的指令还是自定义的指令,都有类似于组件的生命周期,我们可以在不同的生命周期完成不同的逻辑操作,并绑定到组件元素上,这样就产生了自定义指令。在Vue3中,我们有三种方式可以定义指令:

  • 如果是在<script setup>定义组件内的指令,有一个语法糖可以使用:任何以v开头的驼峰式命名的变量都可以被用作一个自定义指令,然后在模板中使用。举一个简单的例子:在输入框渲染后自动聚焦

    <script setup>// 在模板中启用 v-focusconst vFocus = {  mounted: (el) => el.focus()}</script><template>  <input v-focus /></template>

    运行效果:

怎么在Vue3中实现自定义指令

  • 如果是使用选项式,则自定义指令需要在directives选项中注册。同上一个例子:

    <script>export default{  setup() {},  directives: {    // 指令名    focus: {      // 生命周期      mounted(el) {        // 处理DOM的逻辑        el.focus();      },    }  }}</script><template>  <input v-focus /></template>

    实现的效果也是和上一个例子一样。

  • 除了注册组件内指令,我们还可以自定义全局指令,这样在所有的组件中都可以使用该指令

    // main.jsimport { createApp } from 'vue'import App from './App.vue'const app = createApp(App)app.directive('focus', {  mounted(el) {    el.focus();  }})app.mount('#app')

    实现效果也是一样的。

这三种方式我们选择最后一种,其他两种方式可以按照类似的方式实现。

生命周期

指令的生命周期和组件的生命周期类似:

app.directive('focus', {  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');  }})

运行结果:

怎么在Vue3中实现自定义指令

注意指令没有beforeCreated钩子。

  • created:在绑定元素的属性前,或者事件监听器应用前调用

  • beforeMount:在元素被插入到DOM前调用,例如我们想要实现输入框的自动聚焦,就不能在beforeMount钩子中实现

  • mounted:在绑定元素的父组件以及自己的所有子节点都挂载完毕后调用,这个时候DOM已经渲染出来,我们实现输入框自动聚焦也是在这个钩子函数中实现

  • beforeUpdate:绑定元素的父组件更新前调用

  • updated:在绑定元素的父组件以及自己的所有子节点都更新完毕后调用

  • beforeUnmount:绑定元素的父组件卸载前调用

  • unmounted:绑定元素的父组件卸载后调用

每个钩子函数都有对应的参数,接下来继续看钩子参数。

钩子的参数

指令是为了能重用对DOM的操作逻辑,因此指令参数可以有1-4个参数,其中必需的参数就是当前绑定的DOM元素。

语法:

created(el, binding, vnode, preVnode) {}

参数比较多,我们一个一个来学习。

  • el:指令绑定到的DOM元素,可以用于直接操作当前元素,默认传入钩子的就是el参数,例如我们开始实现的focus指令,就是直接操作的元素DOM

  • binding:这是一个对象,包含以下属性:

    • value:在元素上使用指令时,传递给指令的值。例如:<div v-reverse="'hello'"></div>,传递给reserve指令的值就是hello,我们可以拿到值并做相关处理

    • oldValue:之前的值,一般用于beforeUpateupdated钩子函数中,例如:beforeUpdate(el, {oldValue: ''})

    • arg:传递给指令的参数,非必需,例如<div v-reverse:foo="'hello'"></div>,那么传递给指令的参数就是foo

    • modifiers:一个由修饰符构成的对象,例如<div v-reverse.foo.bar="'hello'"></div>,那么该修饰符对象为{foo: true, bar: true},我们经常使用到的事件修饰符,其实和这个差不多。

    • instance:使用该指令的组件实例,注意不是DOM

    • dir:指令的定义对象

  • vnode:绑定元素的地城VNode

  • preVnode:之前的渲染中代表指令所绑定的元素的VNode,一般用于beforeUpateupdated钩子函数中

可能看这些参数会一时迷糊,我们来看一个例子:

定义一个可翻转输入框输入的指令,注意钩子函数要选择beforeUpdate

app.directive('reserve', {  beforeUpdate(el, binding) {    console.log(binding);    el.innerText = binding.value ? binding.value.split('').reverse().join('') : '';  }})

在模板中使用:输入框输入值,div会显示反转后的值

<script setup>import {ref} from 'vue'let hello = ref('')</script><template>  <input v-focus v-model="hello" />  <div v-reserve:foo.bar="hello"></div></template>

运行结果:

怎么在Vue3中实现自定义指令

怎么在Vue3中实现自定义指令

结合该图,是不是就更能理解钩子参数的含义了。

简化形式

我们在写指令的时候,可以具体指定在哪些钩子中执行一些逻辑。有时候指令的钩子不止一个,但是又是重复的逻辑操作时,重复写一遍代码显然有点不够优雅。在Vue中,如果我们在自定义指令时,需要在mountedupdated中实现相同的行为,并且不关心其他钩子的情况,那么我们开可以采用简写:

app.directive('color', (el, binding) => {    // 这将会在mounted和updated时调用    el.style.color = binding.value;})

对象字面量

我们之前的例子中,传递给指令的值只有一个,如果我们想给指令传入多个值应该怎么操作呢?很简单,传入一个字面量对象即可,可以直接在模板中声明,也可以使用响应式对象,在使用时binding.value就是一个对象了,而不是一个普通的值。

<script setup>import {ref, Reactive} from 'vue'let hello = ref('')const obj = reactive({  hello: '',  world: ''})</script><template>  <input v-focus v-model="obj.hello" />  <div v-reserve:foo.bar="obj"></div>  <!-- <div v-reserve:foo.bar="{hello: obj.hello, world: obj.world}"></div> --></template>

对应的,我们的指令也要小小的修改一下:

el.innerText = binding.value ? binding.value.hello.split('').reverse().join('') : '';

实现的效果还是和上面的保持一致。

在组件上使用指令

在元素上直接使用指令,我们可以在指令中操作DOM,这个已经没有问题了。那如果在组件上使用指令会怎样呢?组件其实就是把一些DOM元素封装起来,Vue3和Vue2不同,Vue3的模板中可以不止一个根节点。

我们新建一个Reverse.vue,以便后续作为组件引入。

Vue2:模板中只能有一个根节点,因此会报错

// Reverse.vue<template>    <div></div>    <div></div></template>

Vue3:模板中可以不止一个根节点,正常

// Reverse.vue<template>    <div></div>    <div></div></template>

既然指令是为了操作DOM元素,如果只有单个根节点那不会有问题,例如:

<script setup>...import ReverseVue from './Reserve.vue'...</script><template>  ...  <ReverseVue v-reserve="obj"/></template>
// Reverse.vue<template>    <!-- v-reserve 指令会被应用在此处 -->    <div></div></template>

如果模板中是多个根节点,就会抛出警告,并且不执行指令

// Reverse.vue<template>    <!-- v-reserve 不会作用,并且会抛出警告 -->    <div></div>    <div></div></template>

结论:尽量不要在组件上使用自定义指令,除非能确定只会有一个根节点

几个实用的自定义指令

以下举例的指令都是全局指令

自动聚焦v-focus

聚焦比较特殊,兄弟元素间只会有一个聚焦,即将该指令作用于两个兄弟输入框上,只会自动聚焦一个

app.directive('focus', (el) => {    el.focus();})

防抖v-debounce

在实际项目开发中,经常会听到服务端的同事抱怨:前端怎么不做限流呀。前端做”限流“一般会采用防抖和节流,我们先来看如何实现防抖。

步骤:

  • 首先我们得知道怎么写一个防抖函数

  • 然后需要将防抖函数与el节点绑定,为了通用的话,还需要考虑传入事件类型

  • 最后是卸载定时器等操作

app.directive('debounce', {  mounted(el, binding) {    // 至少需要回调函数以及监听事件类型    if (typeof binding.value.fn !== 'function' || !binding.value.event) return;    let delay = 200; // 默认延迟时间    el.timer = null;    el.handler = function() {      if (el.timer) {        clearTimeout(el.timer);        el.timer = null;      };      el.timer = setTimeout(() => {        binding.value.fn.apply(this, arguments)        el.timer = null;      }, binding.value.delay || delay);    }    el.addEventListener(binding.value.event, el.handler)  },  // 元素卸载前也记得清理定时器并且移除监听事件  beforeMount(el, binding) {    if (el.timer) {      clearTimeout(el.timer);      el.timer = null;    }    el.removeEventListener(binding.value.event, el.handler)  }})

在模板中使用:

<script setup>const handleClick = () => {  console.log('防抖点击');}</script><template>  <button v-debounce="{fn: handleClick, event: 'click', delay: 200}">点击试试</button></template>

运行结果:

快速点击按钮并不会立即触发handleClick,而是会在指定的延迟时间后才会触发。

节流v-throttle

节流和防抖类似,都是用于前端”限流“。不同的是,防抖是限制执行次数,多次密集的触发只会执行最后一次,无规律,更关注结果;节流是限制执行频率,有节奏的执行,有规律, 更关注过程。

节流的实现和防抖差不多:

app.directive('throttle', {  mounted(el, binding) {    // 至少需要回调函数以及监听事件类型    if (typeof binding.value.fn !== 'function' || !binding.value.event) return;    let delay = 200;    el.timer = null;    el.handler = function() {      if (el.timer) return;      el.timer = setTimeout(() => {        binding.value.fn.apply(this, arguments)        el.timer = null;      }, binding.value.delay || delay);    }    el.addEventListener(binding.value.event, el.handler)  },  // 元素卸载前也记得清理定时器并且移除监听事件  beforeMount(el, binding) {    if (el.timer) {      clearTimeout(el.timer);      el.timer = null;    }    el.removeEventListener(binding.value.event, el.handler)  }})

在模板中使用:

<script setup>import {reactive} from 'vue'const obj = reactive({  hello: '',  world: ''})const handleInput = () => {  console.log('节流输入框的值:', obj.hello);}</script><template>  <input v-throttle="{fn: handleInput, event: 'input', delay: 1000}" v-model="obj.hello" /></template>

运行结果:

handleInput并不会因为我在输入框输入时的快慢而触发,而是在固定的时间间隔内触发一次,这就是节流。

弹窗隐藏v-hide

在实际开发时会有这样的需求:点击某一个按钮出现一个弹窗,然后点弹窗的其他区域时需要关闭弹窗,如果是点击的弹窗本身,除非是关闭操作,否则不关闭弹窗。

想要实现这种效果,大多数人都会想到全局监听click事件,并且判断点击的目标元素和我们的弹窗元素是不是同一个,如果不是那就隐藏弹窗。那么我们就来看看具体应该怎么实现:

app.directive('hide', {  mounted(el, binding) {    el.handler = function(e) {      // 如果点击范围在绑定的元素范围内,那么将不执行指令操作,而是执行原点击事件      if (el.contains(e.target)) return;      if (typeof binding.value.fn === 'function') {        // 绑定给指令的如果是一个函数,那么将回调并指定this        binding.value.fn.apply(this, arguments)        // 并不推荐使用style的方式来隐藏元素,这样的话控制弹窗的变量就无法改变,所以推荐使用回调函数        // el.style.display = 'none';        // 解除事件绑定        document.removeEventListener('click', el.handler)      }    }    // 监听全局的点击事件    document.addEventListener('click', el.handler)    // 如果同步绑定全局事件不生效,可以采用异步的方式    // setTimeout(() => {    //   document.addEventListener('click', el.handler)    // }, 0);  },  // 解除事件绑定  beforeMount(el) {    document.removeEventListener('click', el.handler)  }})

在模板中使用:

<script setup>import {ref} from 'vue'let isshowModal = ref(false)const showModal = () => {  isShowModal.value = true;}const cancleModal = () => {  console.log('cancleModal');  isShowModal.value = false;}</script><template>  <button @click.stop="showModal">点击显示弹窗</button>  <div class="modal" v-hide="{fn: cancleModal}" v-if="isShowModal">    <p>我是弹窗</p>    <button @click.stop="cancleModal">关闭</button>  </div></template>

运行结果:

怎么在Vue3中实现自定义指令

到此,关于“怎么在Vue3中实现自定义指令”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注编程网网站,小编会继续努力为大家带来更多实用的文章!

--结束END--

本文标题: 怎么在Vue3中实现自定义指令

本文链接: https://www.lsjlt.com/news/340691.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 怎么在Vue3中实现自定义指令
    这篇文章主要介绍“怎么在Vue3中实现自定义指令”,在日常操作中,相信很多人在怎么在Vue3中实现自定义指令问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”怎么在Vue3中实现自定义指令”的疑惑有所帮助!接下来...
    99+
    2023-07-02
  • vue3的自定义指令directives实现
    目录一、什么是自定义指令二、指令的分类三、指令的作用四、指令的钩子五、钩子参数六、指令的使用指令的参数和修饰符一、什么是自定义指令 我们已经熟悉Vue内置的一系列指令 ,比如 v-m...
    99+
    2022-11-13
  • vue3中怎么自定义指令实现按钮防抖
    这篇“vue3中怎么自定义指令实现按钮防抖”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“vue3中怎么自定义指令实现按钮防抖...
    99+
    2023-07-05
  • 如何在Vue3中实现自定义指令(超详细!)
    目录前言生命周期钩子的参数简化形式对象字面量在组件上使用指令几个实用的自定义指令自动聚焦v-focus防抖v-debounce节流v-throttle弹窗隐藏v-hide总结在开发V...
    99+
    2022-11-13
  • Vue3怎么编写自定义指令插件
    今天小编给大家分享一下Vue3怎么编写自定义指令插件的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。编写自定义插件//&nbs...
    99+
    2023-07-02
  • 怎么写一个Vue3的自定义指令
    本篇内容主要讲解“怎么写一个Vue3的自定义指令”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“怎么写一个Vue3的自定义指令”吧!背景众所周知,Vue.js 的核心思想是数据驱动 + 组件化,通...
    99+
    2023-06-26
  • Vue3中的setup与自定义指令怎么使用
    setup语法糖 最大好处就是所有声明部分皆可直接使用,无需return出去注意:部分功能还不完善,如:name、render还需要单独加入script标签按compositionAPI方式编写// setup 下还可以附加<scri...
    99+
    2023-05-14
    Vue3 setup
  • 一文教你学会在Vue3中自定义指令
    目录1. 成果展示2. 指令基础2.1 两种作用域2.2 七个钩子函数2.3 四个参数2.4 动态参数3. 自定义权限指令TienChin 项目前端是 Vue3,前端有这样的一个需求...
    99+
    2022-11-13
  • vue3自定义指令方法是什么
    这篇文章主要讲解了“vue3自定义指令方法是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“vue3自定义指令方法是什么”吧!一、注册自定义指令以下实例都是实现一个输入框自动获取焦点的自定...
    99+
    2023-06-21
  • Vue中的自定义指令怎么实现
    今天小编给大家分享一下Vue中的自定义指令怎么实现的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。试炼:实现v-mymodel...
    99+
    2023-07-04
  • vue3自定义指令的方法是什么
    这篇文章主要介绍“vue3自定义指令的方法是什么”,在日常操作中,相信很多人在vue3自定义指令的方法是什么问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”vue3自定义指令的方法是什么”的疑惑有所帮助!接下来...
    99+
    2023-07-04
  • Vue.directive中怎么自定义指令
    Vue.directive中怎么自定义指令,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。一、什么是全局API?全局API并不在...
    99+
    2022-10-19
  • Vue3中关于setup与自定义指令详解
    目录setup语法糖 setup语法糖独有 自定义指令相关 setup语法糖  最大好处就是所有声明部分皆可直接使用,无需return出去 注意:部分功能还不完善...
    99+
    2023-05-16
    Vue3 自定义指令 Vue3 setup
  • vue3自定义指令实现按钮防抖示例详解
    目录写在前面自定义指令实现按钮防抖实现思路代码实现总结写在前面 在实际项目开发过程中,对于按钮的提交事件来说,我们需要限制按钮重复点击,避免在某个时间内重复提交。这时候我们一般用到...
    99+
    2023-02-27
    vue3自定义指令按钮防抖 vue 按钮防抖
  • vue3+TS实现自定义指令长按触发绑定的函数
    目录编写自定义指令时遇到的几个难点1.自定义指令的类型2.在ts中使用setTimeout() 函数3.自定义指令的传参问题代码而然间看到一个在vue2中写的长按触发事件的自定义指定...
    99+
    2022-12-29
    vue3 ts自定义指令 vue3 ts自定义长按指令
  • Vue3中的setup与自定义指令如何使用
    本篇内容主要讲解“Vue3中的setup与自定义指令如何使用”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Vue3中的setup与自定义指令如何使用”吧!setup语法糖最大好处就是所有声明部分...
    99+
    2023-07-06
  • vue中自定义指令怎么用
    小编给大家分享一下vue中自定义指令怎么用,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!1、v-drag需求:鼠标拖动元素思路:元素偏移量 = 鼠标滑动后的坐标 - 鼠标初始点击元素时的坐标 + 初始点击时元素距离可视区域...
    99+
    2023-06-22
  • Vue自定义指令怎么写
    小编给大家分享一下Vue自定义指令怎么写,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!什么是Vue指令指令是一种可以附加到DOM...
    99+
    2022-10-19
  • Angular中怎么以Tooltip自定义指令
    本文小编为大家详细介绍“Angular中怎么以Tooltip自定义指令”,内容详细,步骤清晰,细节处理妥当,希望这篇“Angular中怎么以Tooltip自定义指令”文章能帮助大家解决疑惑,下面跟着小编的思...
    99+
    2022-10-19
  • Vue3中怎么自定义Hooks
    本文小编为大家详细介绍“Vue3中怎么自定义Hooks”,内容详细,步骤清晰,细节处理妥当,希望这篇“Vue3中怎么自定义Hooks”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。Composition Api解耦...
    99+
    2023-07-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作