vue3自定义指令 vue中常用自定义指令

news2024/11/19 15:25:41

文章目录

  • vue3自定义指令
    • 1.什么是自定义指令?
    • 2.注册自定义指令
      • 2.1 全局注册
      • 2.2 局部注册
        • `<script setup>`中注册:
        • `<script>`中使用:
    • 3.钩子函数参数详解
    • 4.指令传值
    • 5.总结
  • 常用自定义指令案例
    • v-longpress
    • v-debounce

vue3自定义指令

除了 Vue 内置的一系列指令 (比如 v-model 或 v-show) 之外,Vue 还允许你注册自定义的指令 (Custom Directives)。

我们已经介绍了两种在 Vue 中重用代码的方式:组件和组合式函数。组件是主要的构建模块,而组合式函数则侧重于有状态的逻辑。另一方面,自定义指令主要是为了重用涉及普通元素的底层 DOM 访问的逻辑。

1.什么是自定义指令?

  • 内置指令:
    在Vue中,诸如v-if、v-for、v-on等等被称之为内置指令,它们都是以v-开头的,我们无需注册即可在全局使用它们,内置指令提供了极大的方便给我们,比如v-for指令可以让我们快速循环出很多dom元素等等

  • 自定义指令:
    虽然Vue已经提供了很多内置指令供我们使用,但是人都是贪婪的,总是不满足于现状。所以官方允许我们自定义指令,自定义指令就比较灵活了,我们可以使用任何名称来命名自定义指令,不过我们自定义指定还是需要以v-开头,比如v-focus、v-resize等等。
    如:项目中防抖、节流、点击复制、长按识别、dom拖拽、input 元素自动聚焦这些都可以用自定义指令去完成,但让也可以封装方法,但我感觉还是写成自定义指令比较方便

2.注册自定义指令

在Vue中,如果我们定义了一个组件,我们需要注册它才可以使用。自定义指令也是类似的原理,我们需要先注册自定义指令,然后才可以使用它。

2.1 全局注册

在main.ts文件中

import { createApp } from "vue";
import App from "./App.vue";
const app = createApp(App);
app.directive("focus", {
  // 在绑定元素的 attribute 前
  // 或事件监听器应用前调用
  created(el, binding, vnode, prevVnode) {
  },
  // 在元素被插入到 DOM 前调用
  beforeMount() {},
  // 在绑定元素的父组件
  // 及他自己的所有子节点都挂载完成后调用
  mounted() {},
  // 绑定元素的父组件更新前调用
  beforeUpdate() {},
  // 在绑定元素的父组件
  // 及他自己的所有子节点都更新后调用
  updated() {},
  // 绑定元素的父组件卸载前调用
  beforeUnmount() {},
  // 绑定元素的父组件卸载后调用
  unmounted() {},
});
app.mount("#app");

上段代码中我们借助Vue3提供的directive方法注册了一个全局的自定义指令,该方法接收两个参数:指令名称、指令钩子函数对象。

钩子函数对象和组件的生命周期一样,这也和Vue2中的自定义指令有着较大的区别。理解这些钩子函数也很简单:我们都知道自定义指令是作用在DOM元素上,那么自定义指令从绑定到DOM元素,再到DOM元素发生变化等等一系列操作,都对应了不同的钩子函数,比如当DOM元素插入到文档中时,自定义指令的mounted等钩子函数就会执行。

调用全局注册的自定义指令,代码如下:

<input type="text" v-focus>

我们可以在任意组件中调用它。

2.2 局部注册

由于Vue3中有<script setup><script>两种写法,两种写法对应的自定义指令的注册写法不太一样。

<script setup>中注册:

script setup写法代码更加简介,我一直推荐vue3用 secipt setup,想明白下面的写法,建议参考:vue3语法糖详解(setup()、<script setup>)

<script setup lang="ts">
// 在模板中启用 v-focus
const vFocus = {
  // 在绑定元素的 attribute 前
  // 或事件监听器应用前调用
  created(el, binding, vnode, prevVnode) {},
  // 在元素被插入到 DOM 前调用
  beforeMount() {},
  // 在绑定元素的父组件
  // 及他自己的所有子节点都挂载完成后调用
  mounted() {},
  // 绑定元素的父组件更新前调用
  beforeUpdate() {},
  // 在绑定元素的父组件
  // 及他自己的所有子节点都更新后调用
  updated() {},
  // 绑定元素的父组件卸载前调用
  beforeUnmount() {},
  // 绑定元素的父组件卸载后调用
  unmounted() {},
};
</script>

在Vue3中,只要以小写字母v开头的驼峰命名的变量都可以作为一个自定义指令使用,比如上段代码中vFocus就可以在模板中通过v-focus的指令形式使用。

<script>中使用:

export default {
  setup() {
    /*...*/
  },
  directives: {
    // 在模板中启用 v-focus
    focus: {
      // 在绑定元素的 attribute 前
	  // 或事件监听器应用前调用
	  created(el, binding, vnode, prevVnode) {},
	  // 在元素被插入到 DOM 前调用
	  beforeMount() {},
	  // 在绑定元素的父组件
	  // 及他自己的所有子节点都挂载完成后调用
	  mounted() {},
	  // 绑定元素的父组件更新前调用
	  beforeUpdate() {},
	  // 在绑定元素的父组件
	  // 及他自己的所有子节点都更新后调用
	  updated() {},
	  // 绑定元素的父组件卸载前调用
	  beforeUnmount() {},
	  // 绑定元素的父组件卸载后调用
	  unmounted() {},
    }
  }
}

3.钩子函数参数详解

参考官网文档:自定义指令钩子参数
在这里插入图片描述

4.指令传值

我们讲解钩子函数参数时,里面有一个binding参数,这个参数是一个对象,它里面有很多属性,而这些属性中有些就是指令传的值。binding对象中的value就是。看下面代码

<div class="drag" v-drag:jie="'zhang'"></div>
<script lang="ts">
  directives: {
    drag: {
      created(el, binding, vnode, prevVnode) {
        console.log(el, binding);
      },
    },
  },
</script>

结果看图
在这里插入图片描述

5.总结

自定义指令的用处非常多,如果你领略到了它的魅力,那么我相信你一定会爱上它的。Vue3和Vue2自定义指令在注册和使用上有一点,不同,不过原理都是一样的,所以如果你有Vue2的基础,学会Vue3的自定义指令简直就是信手拈来。

常用自定义指令案例

v-longpress

需求:当用户按下鼠标左键或移动端单指触碰,并按住按钮几秒钟时,视为一次长按,触发对应的函数。

思路:
定义一个计时器, n 秒后执行函数,n作为参数。
当用户按下按钮时触发 mousedown 或touchstart 事件,启动计时器。
如果 click 、 mouseup 、touchend 或 touchcancel 事件在 n 秒内被触发,则清除计时器,视为普通点击事件。
如果计时器没有在 n秒内清除,则视为一次长按,触发对应的函数。


```typescript
<template>
  <button v-longPress="changeMsg">修改message</button>
</template>
<script setup lang="ts">
import { DirectiveBinding, ref, VNode } from 'vue';
const changeMsg = () => {
  console.log('长按');
};
let vLongPress = {
  created(el: HTMLElement, binding: DirectiveBinding, vnode, prevVnode) {
    console.log(binding);
    if (typeof binding.value !== 'function') {
      const compName = vNode.context.name;
      let warn = [
        `longpress:`,
      ]`provided expression '${binding.expression}' is not afunction, but has to be `;
      if (compName) {
        warn += `Found in component '${compName}'`;
      }
      console.warn(warn);
    }
    // 定义变量
    let pressTimer = null;
    // 定义函数处理程序
    // 创建计时器( 1秒后执行函数 )
    let start = (e) => {
      if (e.type === 'click' && e.button !== 0) {
        return;
      }
      if (pressTimer === null) {
        pressTimer = setTimeout(() => {
          // 执行函数
          handler();
        }, 2000);
      }
    };
    // 取消计时器
    let cancel = () => {
      // 检查计时器是否有值
      if (pressTimer !== null) {
        clearTimeout(pressTimer);
        pressTimer = null;
      }
    };
    // 运行函数
    const handler = (e) => {
      // 执行传递给指令的方法
      binding.value(e);
    };
    // 添加事件监听器
    el.addEventListener('mousedown', start);
    el.addEventListener('touchstart', start);
    // 取消计时器
    el.addEventListener('click', cancel);
    el.addEventListener('mouseout', cancel);
    el.addEventListener('touchend', cancel);
    el.addEventListener('touchcancel', cancel);
  },
};
</script>


v-debounce

背景:在开发中,有时遇到要给input或者滚动条添加监听事件,需要做防抖处理。
需求:防止input或scroll事件在短时间内被多次触发,使用防抖函数限制一定时间后触发。

思路:
定义一个延迟执行的方法,如果在延迟时间内再调用该方法,则重新计算执行时间。
将事件绑定在传入的方法上。

<template>
  <div>{{ message }}</div>
  <!-- <button v-debounce="changeMsg">修改message</button> -->
  <button v-debounce="{ fn: changeMsg, time: 3000 }">修改message</button>
</template>
<script setup lang="ts">
import { DirectiveBinding, ref, VNode } from 'vue';
let message = ref('123');
const changeMsg = () => {
  message.value = '张三';
  console.log('改变messag');
};
const vDebounce = {
  created(el: HTMLElement, binding: DirectiveBinding, vnode, prevVnode) {
    console.log(binding);

    let timer: null | number = null;
    el.addEventListener('click', () => {
      if (timer) {
        clearTimeout(timer);
      }
      timer = setTimeout(() => {
        binding.value.fn(); // value = changeMsg
      }, binding.value.time);
    });
  },
  beforeMount() {},
  mounted() {},
  beforeUpdate() {},
  updated() {},
  beforeUnmount() {},
  unmounted() {},
};
</script>

或者:这两个做对比,你会发现不一样,运用更灵活,上面说的理解更深刻

<template>
  <button v-debounce="changeMsg">修改message</button>
</template>
<script setup lang="ts">
import { DirectiveBinding, ref, VNode } from 'vue';
let message = ref<string>('123');
const changeMsg = () => {
  message.value = '张三';
  console.log('改变messag');
};
const vDebounce = (el: HTMLElement, binding: DirectiveBinding) => {
  let timer: null | number = null;
  el.addEventListener('click', () => {
    if (timer) {
      clearTimeout(timer);
    }
    timer = setTimeout(() => {
      binding.value(); // value = changeMsg
    }, 1000);
  });
};
</script>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/791048.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

智能财务分析-亿发财务报表管理系统,赋能中小企业财务数字化转型

对于许多中小企业来说&#xff0c;企业重要部门往往是财务和业务部门。业务负责创收&#xff0c;财务负责控制成本&#xff0c;降低税收风险。但因管理机制和公司运行制度的原因&#xff0c;中小企业往往面临着业务与财务割裂的问题&#xff0c;财务数据不清晰&#xff0c;无法…

2023年下半年广州/深圳软考信息系统项目管理师报名

信息系统项目管理师是全国计算机技术与软件专业技术资格&#xff08;水平&#xff09;考试&#xff08;简称软考&#xff09;项目之一&#xff0c;是由国家人力资源和社会保障部、工业和信息化部共同组织的国家级考试&#xff0c;既属于国家职业资格考试&#xff0c;又是职称资…

Vue3 axios数据请求封装

Vue3 axios数据请求封装 环境&#xff1a;vue3tsvite 首先在项目目录下安装axios 运行 npm install axios 成功后在package.json文件会显示。 目录&#xff1a; request.ts文件代码&#xff1a; import axios from axiosconst request axios.create({baseURL:https://api.…

装配木牛前雷达的2023款创维汽车EV6被评为“最强主动安全车型”

近日&#xff0c;全新升级的2023款创维EV6改款车型接受了中国汽车技术研究中心&#xff08;以下简称“中汽中心”&#xff09;的安全碰撞实验。据称&#xff0c;该款车型在主动安全测试中得分率高达98.97%&#xff0c;这近满分的成绩再次刷新了国内主动安全汽车排行榜&#xff…

Android 之 Paint API —— Typeface (字型)

本节带来Paint API系列的最后一个API&#xff0c;Typeface(字型)&#xff0c;由字义&#xff0c;我们大概可以猜到&#xff0c;这个 API是用来设置字体以及字体风格的&#xff0c;使用起来也非常的简单&#xff01;下面我们来学习下Typeface的一些相关 的用法&#xff01; 官方…

右击不显示TortoiseGit图标处理方法

第一种 右键--》TortoiseGIt--》setting--》Icon Overlays--》Status cache&#xff0c;按照下图设置&#xff0c;然后重启电脑。 第二种 进入注册信息&#xff0c;按照步骤找到HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\ShellIconOverlayIden…

CS144学习笔记(1):Internet and IP

1.网络应用 网络应用可以在世界范围内交换数据&#xff0c;例如你可以通过浏览器读取出版社服务器提供的文章。网络应用的基本模型&#xff1a;两台主机各自在本地运行一个程序&#xff0c;程序通过网络来通信。 最常用的通信模型使用双向可靠字节流&#xff0c;通信的两台主机…

我愿称之为最火爆院校!学科评级A+!就业堪比清北!

一、学校及专业介绍 北京邮电大学&#xff08;Beijing University of Posts and Telecommunications&#xff09;&#xff0c;简称北邮&#xff0c;位于北京市&#xff0c;是中华人民共和国教育部直属、工业和信息化部共建的全国重点大学&#xff0c;位列国家“双一流”建设高校…

队列 的初识

Q: 什么是队列&#xff1f; A: 队列又称消息队列&#xff0c;是一种常用于任务间通信的数据结构&#xff0c;队列可以在任务与任务间、中断和任务间传递信息。 Q: 为什么不使用全局变量&#xff1f; A: 如果使用全局变量&#xff0c;任务1修改了变量 a &am…

IIC外设通信

文章目录 IIC外设简介功能介绍框图简化结构图主机发送流程主机接收流程 IIC外设简介 STM32内部集成了硬件IIC收发电路&#xff0c;可由硬件自动执行时钟生成&#xff0c;起始终止条件生成&#xff0c;应答收发位&#xff0c;数据收发等功能&#xff0c;减轻CPU负担。 功能介绍…

2023年深圳杯数学建模D题基于机理的致伤工具推断

2023年深圳杯数学建模 D题 基于机理的致伤工具推断 原题再现&#xff1a; 致伤工具的推断一直是法医工作中的热点和难点。由于作用位置、作用方式的不同&#xff0c;相同的致伤工具在人体组织上会形成不同的损伤形态&#xff0c;不同的致伤工具也可能形成相同的损伤形态。致伤…

Kubernetes ConfigMap - Secret - 使用ConfigMap来配置 Redis

目录 ConfigMap &#xff1a; 参考文档&#xff1a;k8s -- ConfigMap - 简书 (jianshu.com) K8S ConfigMap使用 - 知乎 (zhihu.com) ConfigMap的作用类型&#xff1a; 可以作为卷的数据来源&#xff1a;使用 ConfigMap 来配置 Redis | Kubernetes 可以基于文件创建 Conf…

【C++】类和对象-封装

1.属性和行为作为整体 2.示例2-设计学生类 3.访问权限 4.class和struct的区别 5.成员属性设置为私有 6.设计案例1-立方体类 在main函数前重新补上isSame函数 在Cube类里面添加issamebyclass&#xff0c;利用成员函数判断两个立方体是否相等 自己写的代码&#xff1a; #in…

开放式耳机怎么选?值得入手的开放式耳机有哪些

与封闭式耳机相比&#xff0c;开放式耳机具有更为自然、真实的音质&#xff0c;能够更好地还原音乐现场的声音环境。以下是几款值得推荐的开放式耳机&#xff0c;都来看看有哪些吧。 Top1、NANK南卡00压开放式耳机 推荐理由&#xff1a;死磕开放式传音技术&#xff0c;音质和…

(十四)InfluxDB仪表盘

以下内容来自 尚硅谷&#xff0c;写这一系列的文章&#xff0c;主要是为了方便后续自己的查看&#xff0c;不用带着个PDF找来找去的&#xff0c;太麻烦&#xff01; 第 14 章 InfluxDB仪表盘 14.1 什么是InfluxDB仪表盘 1、前面已经给大家介绍过InfluxDB的仪表盘功能了。点击…

免费数据恢复方法?这3个不要错过!

朋友们&#xff01;本人是个超级马虎的职场新手&#xff0c;在处理工作的时候总是容易误删重要的报表&#xff01;要知道我光是做一个报表就要花很长时间。大家有什么免费数据恢复的方法给我推荐推荐吗&#xff1f;感谢&#xff01;” 在使用电脑时&#xff0c;我们会在电脑中保…

性能测试工具 Jmeter 引入 jar 包踩过的坑

目录 前言&#xff1a; Jmeter 中调用自己编写 jar 中的类出错 错误日志&#xff1a; 出现以上错误的原因&#xff1a; 解决方法&#xff1a; 前言&#xff1a; JMeter 是一种开源的性能测试工具&#xff0c;可以帮助我们快速地进行网站、应用程序等的性能测试和压力测试…

SSM企业固定资产智能管理系统的设计与实现【纯干货分享,M免费领取源码06298】

摘要 信息化社会内需要与之针对性的信息获取途径&#xff0c;但是途径的扩展基本上为人们所努力的方向&#xff0c;由于站在的角度存在偏差&#xff0c;人们经常能够获得不同类型信息&#xff0c;这也是技术最为难以攻克的课题。针对企业固定资产智能管理系统等问题&#xff0c…

计算机系统结构-多处理机

概念&#xff0c;多处理机指的是&#xff0c;多台含cpu的机器共享一个存储器。 &#xff08;可以通过网络宽带&#xff0c;也可以通过线直连这个存储器。当然他们也可以有自己的私有存储器或者高速缓存&#xff09; 几个cpu公用一个总线&#xff0c;没问题。但是如果十几个cpu…

系统学习Linux-MySQL语句(二)

一、SQL语句类型 DDLDDL&#xff08;Data Definition Language&#xff0c;数据定义语言&#xff09;&#xff1a;用于定义数据库中的各种对象&#xff0c;包括数据库、表、视图、触发器等&#xff0c;常见的 DDL 命令有 CREATE、ALTER、DROPDMLDML&#xff08;Data Manipulat…