学习vue3第八节(自定义指令 directive)

1、自定义指令的作用:

自定义指令是用来操作底层DOM的,尽管vue推崇数据驱动视图的理念,但并非所有情况都适合数据驱动。自定义指令就是一种有效的补充和拓展,不仅仅可用于定义任何DOM操作,并且是可以重复使用。
自定义指令,是由一个包含类似组件生命周期钩子函数的对象组成,钩子函数会接受组件所绑定的元素作为参数

2、组件内的自定义指令:

在 中以 v 开头的驼峰形式命名的对象都可以看做是自定义指令
如:

<template>
  <div class="cntainer">
    <!-- 自定义指令 -->
    <img class="img-box" v-img-rotote src="https://img.yzcdn.cn/vant/cat.jpeg" />
    <div>测试自定义指令</div>
  </div>
</template>

<script setup>
const vImgRotote = {
// 添加自定义指令,图片旋转动效
  bind() {
    console.log('bind')
  },
  update() {
    console.log('update')
  },
  mounted(el) {
    // el 当前绑定的元素对象
    console.log('mounted', el)
    el.addEventListener('mouseover', () => {
      console.log('==mouseover==')
      el.style.transform = 'rotate(360deg)'
      el.style.transition = 'all 0.5s'
    })
    el.addEventListener('mouseleave', () => {
      el.style.transform = 'rotate(0deg)'
      // el.style.transition = 'all 0.5s'
    })
  }
}
</script>

或者直接 写指令js文件,通过文件引入

如: 
import vImgRotote from './v-img-rotote.js' // 自定义的指令文件v-img-rotote.js

3、通常情况下我们会定义一个全局的自定义指令,方便使用

比如自定义防重提交指令
// 声明的防重提交指令文件,直接在main.ts 中引入并且挂载在vue实例上即可全局使用;

import { App, DirectiveBinding } from 'vue'
interface MyEl extends HTMLElement {
    disabled?: boolean
}
export function setupMyReplayClickDirective(app: App) {
    app.directive('myReplayClick', {
        mounted(el: MyEl, binding: DirectiveBinding) {
            el.addEventListener('click', () => {
                if (!el.disabled) {
                    el.disabled = true
                    const timer = setTimeout(() => {
                        el.disabled = false
                        clearTimeout(timer)
                    }, binding.value || 1500)
                }
            })
        },
        // updated(el: MyEl, binding: DirectiveBinding) {
        //     console.log('=updated==el;', el)
        //     console.log('=updated==binding', binding)
        // }
    })
}

main.ts 中如下

import { App, createApp } from 'vue'
import aplication from './App.vue'
// const app = createApp({})
const app = createApp(aplication)
import { setupMyReplayClickDirective } from '@/directives/my-replay-click-directive.ts'
setupMyReplayClickDirective(app)

模板中使用如下:

<template>
  <button v-my-replay-click="1000">提交</button>
  // 因默认是1500毫秒,所以可以不写执行时间,直接写上指令即可
  <button v-my-replay-click>提交</button>
</template>

如图:
在这里插入图片描述
在这里插入图片描述

4、自定义指令的生命周期钩子函数

// 此写法为在setup 中声明方式

const myDirective = {
  // 在绑定元素的 attribute 前
  // 或事件监听器应用前调用
  created(el, binding, vnode, prevVnode) {
    // 下面会介绍各个参数的细节

    // el: 要绑定的DOM元素,可以直接进行DOM操作
    // binding: 一个对象,包含以下属性:
      // value: 指令的值,如果传入了表达式,则为表达式的值,否则为 undefined,
              比如v-my-replay-click="`${1000 + 500 }`" // 可以是变量参数,可以是具体的值
      // oldValue:之前的值,仅在 beforeUpdate 和 updated 中可用。无论值是否更改,它都可用
      // arg: 指令的参数,也即 v-bind:arg="value" 中的 arg
      // modifiers:一个包含修饰符的对象 (如果有的话)。例如在 v-my-directive.foo.bar 中,修饰符对象是 { foo: true, bar: true }
      // instance:使用该指令的组件实例
      // dir:指令的定义对象
    // vnode: 代表绑定元素的底层 VNode:
    // prevNode:代表之前的渲染中指令所绑定元素的 VNode。仅在 beforeUpdate 和 updated 钩子中可用。

  },
  // 在元素被插入到 DOM 前调用
  beforeMount(el, binding, vnode, prevVnode) {},
  // 在绑定元素的父组件
  // 及他自己的所有子节点都挂载完成后调用
  mounted(el, binding, vnode, prevVnode) {},
  // 绑定元素的父组件更新前调用
  beforeUpdate(el, binding, vnode, prevVnode) {},
  // 在绑定元素的父组件
  // 及他自己的所有子节点都更新后调用
  updated(el, binding, vnode, prevVnode) {},
  // 绑定元素的父组件卸载前调用
  beforeUnmount(el, binding, vnode, prevVnode) {},
  // 绑定元素的父组件卸载后调用
  unmounted(el, binding, vnode, prevVnode) {}
}

通常情况下,我们在自定义指令时候,只需要在mounted 和updated上执行相关的逻辑,因此我们并不需要其他生命钩子函数,比如:

<div v-my-num=200>改变数字</div>
app.description('myNum', (el, bind) => {
  console.log('====,el,bind)
  el.innerText = `改变数字--${bind.value}`
})

**

5、组件上不建议使用自定义指令,因为自定义指令需要作用在根节点上,vue3组件中可能同时存在多个根节点;

**

仅代表自己观点,如有错误及不合适地方,欢迎批评指正

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

[蓝桥杯 2020 省 AB3] 限高杆

分层图建图典题 #include<bits/stdc.h> using namespace std; using ll long long; #define int long long const int N 6e510; const int inf 0x3f3f3f3f; const int mod 1e97; int e[N],ne[N],w[N],h[N],idx; void add(int a,int b,int c){e[idx] b,ne[idx] h[a]…

DOcker搭建Rancher

简介 Rancher 是供采用容器的团队使用的完整软件堆栈。它解决了管理多个Kubernetes集群的运营和安全挑战&#xff0c;并为DevOps团队提供用于运行容器化工作负载的集成工具。 官网地址&#xff1a;https://www.rancher.cn/ 安装 拉取镜像 docker pull rancher/rancher:stab…

Kotlin中单例模式和Java的对比浅析

前言 单例模式&#xff0c;一直以来是我们在日常开发中最常用的一种设计模式&#xff0c;更是面试中非常重要&#xff0c;也非常容易被问到的问题。在日常开发中&#xff0c;大家常用的语言还是Java&#xff0c;但今天我给大家带来的是在Kotlin语言中&#xff0c;单例模式是怎…

【视觉语言大模型+LLaVA1.0】大语言模型视觉助手(视觉指令调优)GPT4-Vision丐版

官方资源汇总&#xff1a; 项目主页 || https://huggingface.co/liuhaotian 23.04.LLaVA1.论文: Large Language and Vision Assistant&#xff08;Visual Instruction Tuning) 23.10 LLaVA-1.5论文: Improved Baselines with Visual Instruction Tuning 23.11 LLaVA-Plus项目&…

基于python+vue智慧社区家政服务系统的设计与实现flask-django-nodejs

论文主要是对智慧社区家政服务系统进行了介绍&#xff0c;包括研究的现状&#xff0c;还有涉及的开发背景&#xff0c;然后还对系统的设计目标进行了论述&#xff0c;还有系统的需求&#xff0c;以及整个的设计方案&#xff0c;对系统的设计以及实现&#xff0c;也都论述的比较…

【Thread 线程】线程的方法与状态

SueWakeup 个人中心&#xff1a;SueWakeup 系列专栏&#xff1a;学习Java 个性签名&#xff1a;保留赤子之心也许是种幸运吧 本文封面由 凯楠&#x1f4f7; 友情赞助播出&#xff01; 目录 一个线程的生命周期 线程终止的原因 线程的方法 Thread 类的静态方法 1. 设置线程…

六、C#快速排序算法

简介 快速排序是一种常用的排序算法&#xff0c;它基于分治的思想&#xff0c;通过将一个无序的序列分割成两个子序列&#xff0c;并递归地对子序列进行排序&#xff0c;最终完成整个序列的排序。 其基本思路如下&#xff1a; 选择数组中的一个元素作为基准&#xff08;pivot…

第四百一十二回

文章目录 1. 概念介绍2. 思路与方法2.1 实现思路2.2 实现方法 3. 示例代码4. 内容总结 我们在上一章回中介绍了"给geolocator插件提交问题的结果"相关的内容&#xff0c;本章回中将介绍自定义标题栏.闲话休提&#xff0c;让我们一起Talk Flutter吧。 1. 概念介绍 我…

KKVIEW远程控制 手机远程控制电脑

机远程控制电脑&#xff1a;实现跨设备便捷操作 随着科技的飞速发展&#xff0c;智能手机和电脑已成为我们日常生活中不可或缺的工具。有时&#xff0c;我们可能需要在不直接接触电脑的情况下对其进行操作&#xff0c;这时&#xff0c;手机远程控制电脑的技术就显得尤为重要。…

深入理解栈和队列(一):栈

个人主页&#xff1a;17_Kevin-CSDN博客 专栏&#xff1a;《数据结构》 一、栈的概念 栈&#xff08;Stack&#xff09;是一种特殊的线性表&#xff0c;它遵循后进先出&#xff08;Last-In-First-Out&#xff0c;LIFO&#xff09;的原则。栈可以被看作是一个只能在一端进行操作…

内网横向移动小结

windows Windows-Mimikatz 适用环境&#xff1a; 微软为了防止明文密码泄露发布了补丁 KB2871997&#xff0c;关闭了 Wdigest 功能。当系统为 win10 或 2012R2 以上时&#xff0c;默认在内存缓存中禁止保存明文密码&#xff0c;此时可以通过修改注册表的方式抓取明文&#xff…

selenium 元素定位攻略大全

一、By类单一属性定位 元素名称描述Webdriver APIidid属性driver.find_element(By.ID, "id属性值")namename属性driver.find_element(By.NAME, "name属性值")class_nameclass属性driver.find_element(By.CLASS_NAME, "class_name属性值")tag_na…

Angular进阶之八: Angular Animation在项目中的实践经验

使用 Angular 进行项目开发的程序员应该都很熟悉 Angular Animation。这是一个 Angular 原生的动画库&#xff0c;它可以替代或者辅助完成原本需要使用 css 的动画功能。 Angular 在国内的运用是很有限的&#xff0c;可借鉴的文档并不很丰富。尤其对于 Angular 动画模块的应用…

中间件-消息队列

消息队列基础知识 什么是消息队列 本处提到的消息队列是指各个服务以及系统组件/模块之间的通信&#xff0c;属于一种中间件。参与消息传递的双方称为生产者和消费者&#xff0c;生产者负责发送消息&#xff0c;消费者负责处理消息。 消息队列作用 通过异步处理&#xff0…

Node.js安装Vue3安装

文章目录 前言Node.js安装设置Node.js系统变量Vue3安装 前言 前端初学者注意&#xff1a;node.js 先安装后才能安装vue3&#xff0c;node.js在安装时会自动安装npm Node.js安装 安装包已上传CSDN,审核中 &#xff0c; 也可以nodejs官网下载 默认C盘&#xff0c;本人下载路径…

idea import的maven类报红

idea 报红/显示红色的原因 一般报红&#xff0c;显示红色&#xff0c;是因为 idea 在此路径下&#xff0c;找不到这个类。 找到是哪个 jar 包的类导致 idea 报红 点击报红的路径的上一层&#xff0c;进入jar 包。比如&#xff1a; import com.aaa.bbb.ccc.DddDto;这个 impo…

K8s-网络原理-上篇

引言 本文是学习《深入剖析K8s》网络原理部分的学习笔记&#xff0c;相关图片和案例可以从https://github.com/WeiXiao-Hyy/k8s_example获取&#xff0c;欢迎Star&#xff01; 网络基础 IP组成 IP地址由两部分组成&#xff0c;即网络地址和主机地址。网络地址表示其属于互联…

03.生命周期和工程化开发入门

一、Vue生命周期 思考&#xff1a;什么时候可以发送初始化渲染请求&#xff1f;&#xff08;越早越好&#xff09;什么时候可以开始操作dom&#xff1f;&#xff08;至少dom得渲染出来&#xff09; Vue生命周期&#xff1a;就是一个Vue实例从创建 到 销毁 的整个过程。 生命…

TikTok云手机是什么原理?

随着社交媒体的快速发展和普及&#xff0c;TikTok已成为全球最受欢迎的短视频平台之一&#xff0c;吸引了数以亿计的用户。在TikTok上&#xff0c;许多用户和内容创作者都希望能够更灵活地管理和运营多个账号&#xff0c;这就需要借助云手机技术。那么&#xff0c;TikTok云手机…

10-项目部署_持续集成-黑马头条

项目部署_持续集成 1 今日内容介绍 1.1 什么是持续集成 持续集成&#xff08; Continuous integration &#xff0c; 简称 CI &#xff09;指的是&#xff0c;频繁地&#xff08;一天多次&#xff09;将代码集成到主干 持续集成的组成要素 一个自动构建过程&#xff0c; 从…
最新文章