【Vue3】自定义指令

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

1. 生命周期钩子函数

一个自定义指令由一个包含类似组件生命周期钩子的对象来定义。钩子函数会接收到指令所绑定元素作为其参数。

<script setup> 中,任何以 v 开头的驼峰式命名的变量都可以被用作一个自定义指令。

<!-- App.vue -->
<template><div><button>切换</button><!-- 钩子函数里面都可以接受这些值myParam: 自定义参数;myModifier: 自定义修饰符 --><A v-move:myParam.myModifier="{ background: 'pink' }"></A></div>
</template><script setup lang="ts">
import { reactive, ref, Directive } from 'vue';
import A from './components/A.vue';
import B from './components/B.vue';
let flag = ref<boolean>(true)
const vMove: Directive = {created() {console.log('created')},beforeMount() {console.log('beforeMount')},mounted(...args: Array<any>) {console.log('mounted')console.log(args);},beforeUpdate() {console.log('beforeUpdate')},updated() {console.log('updated')},beforeUnmount() {console.log('beforeUnmount')},unmounted() {console.log('unmounted')}
}
</script><style scoped lang="less"></style>

在这里插入图片描述

  • 0:该 div 元素。
  • 1:传入的参数等。比如 arg 参数,modifiers 自定义修饰符,dir 目录,传入的 value 值,instance 组件实例。
  • 2:当前组件的虚拟 DOM
  • 3:上一个虚拟 DOM
<!-- App.vue -->
<template><div><button>切换</button><!-- 钩子函数里面都可以接受这些值myParam: 自定义参数;myModifier: 自定义修饰符 --><A v-move:myParam.myModifier="{ background: 'pink' }"></A></div>
</template><script setup lang="ts">
import { reactive, ref, Directive, DirectiveBinding } from 'vue';
import A from './components/A.vue';
import B from './components/B.vue';
let flag = ref<boolean>(true)
type Dir = {background: string;
}
const vMove: Directive = {created() {console.log('created')},beforeMount() {console.log('beforeMount')},mounted(el: HTMLElement, dir: DirectiveBinding<Dir>) {console.log('mounted')console.log(el);console.log(dir);el.style.background = dir.value.background;},// 传入的数据发生变化(比如此时的background)时触发 beforeUpdate 和 updatedbeforeUpdate() {console.log('beforeUpdate')},updated() {console.log('updated')},beforeUnmount() {console.log('beforeUnmount')},unmounted() {console.log('unmounted')}
}
</script><style scoped lang="less"></style>

在这里插入图片描述

2. 指令简写

<!-- App.vue -->
<template><div class="btns"><button v-has-show="123">创建</button><button>编辑</button><button>删除</button></div>
</template><script setup lang="ts">
import { reactive, ref, DirectiveBinding } from 'vue';
import type { Directive } from 'vue'
const vHasShow: Directive = (el, binding) => {console.log(el, binding) ;
}
</script><style scoped lang="less">
.btns {button {margin: 10px;}
}
</style>

在这里插入图片描述

应用场景1:按钮鉴权

根据能否从 localStorage(或者后台返回) 中获取数据,来判断是否显示某个按钮。

<!-- App.vue -->
<template><div class="btns"><button v-has-show="'shop:create'">创建</button><button v-has-show="'shop:edit'">编辑</button><button v-has-show="'shop:delete'">删除</button></div>
</template><script setup lang="ts">
import { reactive, ref, DirectiveBinding } from 'vue';
import type { Directive } from 'vue'
localStorage.setItem('userId', 'xiuxiu')
// mock 后台返回的数据
const permissions = ['xiuxiu:shop:create',// 'xiuxiu:shop:edit',  // 后台没有相应数据,则不显示该对应的按钮'xiuxiu:shop:delete'
]
const userId = localStorage.getItem('userId') as string
const vHasShow: Directive = (el, binding) => {if(!permissions.includes(userId + ':' + binding.value)) {el.style.display = 'none'}
}
</script><style scoped lang="less">
.btns {button {margin: 10px;}
}
</style>

在这里插入图片描述

应用场景2:鼠标拖拽

拖拽粉色框移动大盒子。

<!-- App.vue -->
<template><div v-move class="box"><div class="header"></div><div>内容</div></div>
</template><script setup lang="ts">
import { Directive, DirectiveBinding } from 'vue';const vMove:Directive<any,void> = (el:HTMLElement, binding:DirectiveBinding)=> {let moveElement:HTMLElement = el.firstElementChild as HTMLElement;console.log(moveElement);const mouseDown = (e:MouseEvent) => {// 记录原始位置// clientX 鼠标点击位置的X轴坐标// clientY 鼠标点击位置的Y轴坐标// offsetLeft 鼠标点击的子元素距离其父元素的左边的距离// offsetTop 鼠标点击的子元素距离其父元素的顶部的距离let X = e.clientX - el.offsetLeft;let Y = e.clientY - el.offsetTop;const move = (e:MouseEvent) => {console.log(e);el.style.left = e.clientX - X + 'px';el.style.top = e.clientY - Y + 'px';}document.addEventListener('mousemove', move);document.addEventListener('mouseup', () => {document.removeEventListener('mousemove', move);})}moveElement.addEventListener('mousedown', mouseDown);
}
</script><style scoped lang="less">
.box {position: fixed;height: 200px;width: 200px;top: 50%;left: 50%;transform: translate(-50%, -50%);border: 1px solid #000;.header {height: 50px;width: 100%;background: pink;border-bottom: #000 1px solid;}
}
</style>

在这里插入图片描述

应用场景3:懒加载

let imageList = import.meta.glob('./assets/images/*.*', { eager: true })

在这里插入图片描述

let imageList = import.meta.glob('./assets/images/*.*')

在这里插入图片描述

 // 判断图片是否在可视区const observer = new IntersectionObserver((e)=> {console.log(e[0]);})  // 监听元素observer.observe(el)

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

<!-- App.vue -->
<template><div><div><img v-lazy="item" width="400" height="500" v-for="item in arr" alt=""></div></div>
</template><script setup lang="ts">
import { Directive, DirectiveBinding } from 'vue';let imageList:Record<string,{default:string}> = import.meta.glob('./assets/images/*.*', { eager: true })
let arr = Object.values(imageList).map(item=>item.default)
console.log(arr);
let vLazy:Directive<HTMLImageElement,string> = async (el,binding)=> {const def = await import('./assets/pinia.svg')el.src = def.default// 判断图片是否在可视区const observer = new IntersectionObserver((e)=> {console.log(e[0],binding.value);if(e[0].intersectionRatio > 0) {setTimeout(()=> {el.src = binding.value},2000)observer.unobserve(el)}})  // 监听元素observer.observe(el)
}
</script><style scoped lang="less"></style>
  1. 进入可视区比例 > 0:

    在这里插入图片描述

  2. 过 2s ,替换图片

    在这里插入图片描述

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

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

相关文章

【多线程】进程与线程 并发编程 面试题总结

进程和线程 进程是程序执行时的一个实例&#xff0c;即它是程序已经执行到何种程度的数据结构的汇集。从内核的观点看&#xff0c;进程的目的就是担当分配系统资源&#xff08;CPU时间、内存等&#xff09;的基本单位。线程是进程的一个执行流&#xff0c;是CPU调度和分派的基…

使用docker完成minio服务部署扩容备份迁移生产实践文档

一、minio服务扩容方案 当服务器存储空间不足的时候&#xff0c;需要进行扩容&#xff0c;扩容过程中需要短暂停机时间&#xff0c;预计在一小时内能够完成和恢复 统一注意事项 强烈建议为部署中的所有节点选择基本相似的硬件配置。确保硬件&#xff08;CPU、内存、主板、存…

Excel·VBA日期时间转换提取正则表达式函数

标准日期转换 Function 标准日期(ByVal str$) As DateDim pat$, result$arr Array("(\d{4}).*?(\d{1,2}).*?(\d{1,2})", "(\d{4}).*?(\d{1}).*?(\d{1,2})")If Len(str) < 8 Then pat arr(1) Else pat arr(0)With CreateObject("vbscript.r…

java的内存模型(概念)

在java中&#xff0c;设计之初就有了&#xff1a;主内存、线程工作内存&#xff0c;所以其实每一个线程执行时&#xff0c;都是将主线程copy一份到工作线程&#xff0c;执行修改后&#xff0c;再同步回去。 所以&#xff0c;就有四组内存操作方式&#xff1a; 1、读主内存&…

微信小程序 table表格 固定表头和首列 右侧表格可以左右滚动

(一) 1.左侧一列固定不动 2.右侧表格内容可以左右滚动 3.单元格内容平均分配 4.每一行行高可以由内容撑开 通过 js 设置左侧一列行高与右侧表格内容行高保持一致 1.1 效果图 1.2 tabble.wxml <view classtable><!-- 左侧固定 --><view classtable_left_colum…

【Aseprite像素画】如何取巧做到各种画面效果(小工具的各种技巧)

文章目录 参考链接&#xff1a;具体如下1、水中倒影2、参考图片3多个帧添加动画物品4多个帧删除动画物品5六毛钱受击效果6添加标签7导出特定标志的gif图8忽略标志帧&#xff0c;然后播放9轮廓线10多个图层轮廓线11洋葱皮12替换多个不同帧的色块簇13连接细胞14快速连续删除15冻结…

关于将对象转成JSON格式的一些问题

1.问题现象&#xff1a; 在ssm项目中&#xff0c;一个controller返回Msg对象&#xff08;自定义Javabean对象&#xff09;&#xff0c;然后利用SpringMVC的ResponseBody注解自动将Msg对象转化成JSON格式&#xff0c;返回给客户端&#xff0c;但是客户端接收到的json字符串只有…

SwiftUI 4.0:两种方式实现子视图导航功能

0. 概览 从 SwiftUI 4.0 开始&#xff0c;觉悟了的苹果毅然抛弃了已“药石无效”的 NavigationView&#xff0c;改为使用全新的 NavigationStack 视图。 诚然&#xff0c;NavigationStack 从先进性来说比 NavigationView 有不小的提升&#xff0c;若要如数家珍得单开洋洋洒洒…

高效的开发流程搭建

目录 1. 搭建 AI codebase 环境kaggle的服务器1. 搭建 AI codebase 环境 python 、torch 以及 cuda版本,对AI的影响最大。不同的版本,可能最终计算出的结果会有区别。 硬盘:PCIE转SSD的卡槽,, GPU: 软件源: Anaconda: 一定要放到固态硬盘上。 VS code 的 debug功能…

【NLP的python库(03/4) 】: 全面概述

一、说明 Python 对自然语言处理库有丰富的支持。从文本处理、标记化文本并确定其引理开始&#xff0c;到句法分析、解析文本并分配句法角色&#xff0c;再到语义处理&#xff0c;例如识别命名实体、情感分析和文档分类&#xff0c;一切都由至少一个库提供。那么&#xff0c;你…

Pikachu-xxe (xml外部实体注入漏洞)过关笔记

Pikachu-xxe过关笔记 有回显探测是否有回显file:///协议查看本地系统文件php://协议查看php源代码&#xff08;无法查看当前网页代码&#xff0c;只能看别的&#xff09;http://协议爆破开放端口&#xff08;两者的加载时间不同&#xff09; 无回显第一步第二步第三步 运行结果…

SketchUp Pro 2023 for Mac——打造你的创意之城

SketchUp Pro 2023 for Mac是一款专业级的3D建模软件&#xff0c;为你提供最佳的设计和创意工具。不论你是建筑师、室内设计师&#xff0c;还是爱好者&#xff0c;SketchUp Pro都能满足你对于创意表达的需求。 SketchUp Pro 2023拥有强大而直观的界面&#xff0c;让你轻松绘制…

C++算法 —— 动态规划(10)二维费用背包

文章目录 1、动规思路简介2、一和零3、盈利计划 背包问题需要读者先明白动态规划是什么&#xff0c;理解动规的思路&#xff0c;并不能给刚接触动规的人学习。所以最好是看了之前的动规博客&#xff0c;以及两个背包博客&#xff0c;或者你本人就已经懂得动规了。 1、动规思路简…

Java+Redis:布隆过滤器,打造高效数据过滤神器!

&#x1f389;&#x1f389;欢迎来到我的CSDN主页&#xff01;&#x1f389;&#x1f389; &#x1f3c5;我是尘缘&#xff0c;一个在CSDN分享笔记的博主。&#x1f4da;&#x1f4da; &#x1f449;点击这里&#xff0c;就可以查看我的主页啦&#xff01;&#x1f447;&#x…

postgresql16-新特性

postgresql16-新特性 any_value数组抽样数组排序 any_value any_value 返回任意一个值 select e.department_id ,count(*), any_value(e.last_name) from cps.public.employees e group by e.department_id ;数组抽样 -- 从数组中随机抽取一个元素 array_sample(数组&#…

C++:stl:stack、queue、priority_queuej介绍及模拟实现和容量适配器deque介绍。

本文主要介绍c中stl的栈、队列和优先级队列并对其模拟实现&#xff0c;对deque进行一定介绍并在栈和队列的模拟实现中使用。 目录 一、stack的介绍和使用 1.stack的介绍 2.stack的使用 3.stack的模拟实现 二、queue的介绍和使用 1.queue的介绍 2.queue的使用 3.queue的…

插上u盘显示格式化怎么办?U盘数据恢复可以这样做

U盘以其体积小巧、存储容量大、读写速度快的特点&#xff0c;在各种工作和个人使用场合中得到了广泛应用&#xff0c;因此深得用户好评。然而&#xff0c;在日常使用U盘的过程中&#xff0c;经常会遇到一些问题和挑战。 当我需要转移一些资料文件时&#xff0c;总是喜欢使用U盘…

基于spring boot的医疗管理系统 /基于java的医疗系统

摘 要 随着信息技术和网络技术的飞速发展&#xff0c;人类已进入全新信息化时代&#xff0c;传统管理技术已无法高效&#xff0c;便捷地管理信息。为了迎合时代需求&#xff0c;优化管理效率&#xff0c;各种各样的管理系统应运而生&#xff0c;各行各业相继进入信息管理时代&a…

一键智能视频语音转文本——基于PaddlePaddle语音识别与Python轻松提取视频语音并生成文案

前言 如今进行入自媒体行业的人越来越多&#xff0c;短视频也逐渐成为了主流&#xff0c;但好多时候是想如何把视频里面的语音转成文字&#xff0c;比如&#xff0c;录制会议视频后&#xff0c;做会议纪要&#xff1b;比如&#xff0c;网课教程视频&#xff0c;想要做笔记&…

[架构之路-225]:计算机硬件与体系结构 - 分类方法大汇总: RISC, CISC

目录 一、分类方法汇总 二、指令流和数据流的关系分类 三、Flynn 分类&#xff1a;指令并行处理 四、根据指令集架构&#xff08;ISA&#xff09;分类 4.1 分类 4.2 开源的RISC-V与封闭的RISC指令集架构比较 4.3 RISC-V的演进路径 4.4 RISC-V与中国芯片自研 4.4 五阶流…