【Vue3】自定义指令
除了 Vue 内置的一系列指令 (比如 v-model 或 v-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>
-
进入可视区比例 > 0:

-
过 2s ,替换图片

相关文章:
【Vue3】自定义指令
除了 Vue 内置的一系列指令 (比如 v-model 或 v-show) 之外,Vue 还允许你注册自定义的指令 (Custom Directives)。 1. 生命周期钩子函数 一个自定义指令由一个包含类似组件生命周期钩子的对象来定义。钩子函数会接收到指令所绑定元素作为其参数。 在 <script …...
UG\NX CAM二次开发 加工模块获取 UF _ask_application_module
文章作者:代工 来源网站:NX CAM二次开发专栏 简介: UG\NX CAM二次开发 加工模块获取 UF _ask_application_module 代码: void MyClass::do_it() { // TODO: add your code here // 获取NX当前所在的模块 int module_id = 0; // UF_ask_application_module(&…...
借助GPU算力编译Android
借助GPU算力编译Android 借助GPU编译Android代码的意义在于提高编译的效率和速度。传统的CPU编译方式在处理大量代码时可能会遇到性能瓶颈,而GPU编译利用了显卡的并行计算能力,可以同时处理多个任务,加快编译过程。通过利用GPU的并行计算能力,可以将编译过程中的多个任务分…...
docker-compose一键部署mysql
1.创建安装目录 mnt为硬盘挂载目录,根据实际情况修改 mkdir -p /mnt/mysql cd /mnt/mysql vim docker-compose.yml2.编写docker-compose.yml version: 3.1 services:db:image: mysql:5.7 #mysql版本volumes:- ./data/db:/var/lib/mysql #数据文件- ./etc/my.cnf:/…...
MATLAB 函数签名器
文章目录 MATLAB 函数签名器注释规范模板参数类型 kind数据格式 type选项的支持 使用可执行程序封装为m函数程序输出 编译待办事项推荐阅读附录 MATLAB 函数签名器 MATLAB 函数签名器 (FUNCSIGN) ,在规范注释格式的基础上为函数文件或类文件自动生成函数签名&#…...
2019强网杯随便注bugktu sql注入
一.2019强网杯随便注入 过滤了一些函数,联合查询,报错,布尔,时间等都不能用了,尝试堆叠注入 1.通过判断是单引号闭合 ?inject1-- 2.尝试堆叠查询数据库 ?inject1;show databases;-- 3.查询数据表 ?inject1;show …...
Html+Css+Js计算时间差,返回相差的天/时/分/秒(从未来的一个日期时间到当前日期时间的差)。
Html部分 <!DOCTYPE html> <html><head><meta charset"utf-8" /><title></title><link rel"stylesheet" type"text/css" href"css/index.css" /><script src"js/index.js" t…...
mybatis项目启动报错:reader entry: ���� = v
问题再现 解决方案一 由于指定的VFS没有找,mybatis启用了默认的DefaultVFS,然后由于DefaultVFS的内部逻辑,从而导致了reader entry乱码。 去掉mybatis配置文件中关于别名的配置,然后在mapper.xml文件中使用完整的类名。 待删除的…...
【GIT版本控制】--什么是版本控制
一、为什么需要版本控制? 版本控制是在软件开发和许多其他领域中非常重要的工具,因为它解决了许多与协作、追踪更改和管理项目相关的问题。以下是一些主要原因,解释了为什么需要版本控制: 追踪更改历史: 版本控制系统允许您准确…...
ChatGPT付费创作系统V2.3.4独立版 +WEB端+ H5端 + 小程序最新前端
人类小徐提供的GPT付费体验系统最新版系统是一款基于ThinkPHP框架开发的AI问答小程序,是基于国外很火的ChatGPT进行开发的Ai智能问答小程序。当前全民热议ChatGPT,流量超级大,引流不要太简单!一键下单即可拥有自己的GPT࿰…...
GEE16: 区域日均降水量计算
Precipitation 1. 区域日均降水量计算2. 降水时间序列3. 降水数据年度时间序列对比分析 1. 区域日均降水量计算 今天分析一个计算区域日均降水量的方法: 数据信息: Climate Hazards Group InfraRed Precipitation with Station data (CHIRPS) is a…...
打开MySQL数据库
在命令行里输入mysql --version就可以查看: mysql -uroot -p之前设置的密码(不用输入)就可登录成功:...
玩转ChatGPT:DALL·E 3生成图像
一、写在前面 好久不更新咯,因为没有什么有意思的东西分享的。 今天更新,是因为GPT整合了自家的图像生成工具,名字叫作DALLE 3。 DALLE 3是OpenAI推出的一种生成图像的模型,它基于GPT-3架构进行训练,但是它的主要目…...
小程序入门笔记(一) 黑马程序员前端微信小程序开发教程
微信小程序基本介绍 小程序和普通网页有以下几点区别: 运行环境:小程序可以在手机的操作系统上直接运行,如微信、支付宝等;而普通网页需要在浏览器中打开才能运行。 开发技术:小程序采用前端技术进行开发,…...
【进程管理】初识进程
一.何为进程 教材一般会给出这样的答案: 运行起来的程序 或者 内存中的程序 这样说太抽象了,那我问程序和进程有什么区别呢?诶?这我知道,书上说,动态的叫进程,静态的叫程序。那么静态和动态又是什么意思…...
ArcGIS Maps SDK for JS:监听按钮点击事件控制图层的visible属性
文章目录 1 需求描述2 解决方案 1 需求描述 现在有这么一个需求:在地图中添加一些图层,添加图层列表按钮。打开图层列表后用户会打开某些图层使其可见,要求关闭图层列表时,隐藏某些图层(若visibletrue) 2…...
微信小程序-1
微信开发文档 https://developers.weixin.qq.com/miniprogram/dev/framework/ 报错在调试器的console里找 一、结构 Ctrl 放大字体 Ctrl - 缩小 设置 - - - 外观设置 - - - 可以修改喜欢的主题颜色 index.js index.json index.wxml 》 html <view class"box&qu…...
不容易解的题10.5
31.下一个排列 31. 下一个排列 - 力扣(LeetCode)https://leetcode.cn/problems/next-permutation/?envTypelist&envIdZCa7r67M会做就不算难题,如果没做过不知道思路,这道题将会变得很难。 这道题相当于模拟cpp的next_permu…...
后端面经学习自测(二)
文章目录 1、Http1.1和2.0的区别大概是什么?HTTP & HTTPS 2、HTTP,用户后续的操作,服务端如何知道属于同一个用户cookie & session & token手机验证码登录流程SSO单点登录 3、如果服务端是一个集群机器?4、hashmap是线…...
使用Jest测试Cesium源码
使用Jest测试Cesium源码 介绍环境Cesium安装Jest安装Jest模块包安装babel安装Jest的VSC插件 测试例子小结 介绍 在使用Cesium时,我们常常需要编写自己的业务代码,其中需要引用Cesium的源码,这样方便调试。此外,目前代码中直接使用…...
vscode里如何用git
打开vs终端执行如下: 1 初始化 Git 仓库(如果尚未初始化) git init 2 添加文件到 Git 仓库 git add . 3 使用 git commit 命令来提交你的更改。确保在提交时加上一个有用的消息。 git commit -m "备注信息" 4 …...
关于nvm与node.js
1 安装nvm 安装过程中手动修改 nvm的安装路径, 以及修改 通过nvm安装node后正在使用的node的存放目录【这句话可能难以理解,但接着往下看你就了然了】 2 修改nvm中settings.txt文件配置 nvm安装成功后,通常在该文件中会出现以下配置&…...
1688商品列表API与其他数据源的对接思路
将1688商品列表API与其他数据源对接时,需结合业务场景设计数据流转链路,重点关注数据格式兼容性、接口调用频率控制及数据一致性维护。以下是具体对接思路及关键技术点: 一、核心对接场景与目标 商品数据同步 场景:将1688商品信息…...
AI编程--插件对比分析:CodeRider、GitHub Copilot及其他
AI编程插件对比分析:CodeRider、GitHub Copilot及其他 随着人工智能技术的快速发展,AI编程插件已成为提升开发者生产力的重要工具。CodeRider和GitHub Copilot作为市场上的领先者,分别以其独特的特性和生态系统吸引了大量开发者。本文将从功…...
汇编常见指令
汇编常见指令 一、数据传送指令 指令功能示例说明MOV数据传送MOV EAX, 10将立即数 10 送入 EAXMOV [EBX], EAX将 EAX 值存入 EBX 指向的内存LEA加载有效地址LEA EAX, [EBX4]将 EBX4 的地址存入 EAX(不访问内存)XCHG交换数据XCHG EAX, EBX交换 EAX 和 EB…...
多模态大语言模型arxiv论文略读(108)
CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文标题:CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文作者:Sayna Ebrahimi, Sercan O. Arik, Tejas Nama, Tomas Pfister ➡️ 研究机构: Google Cloud AI Re…...
ios苹果系统,js 滑动屏幕、锚定无效
现象:window.addEventListener监听touch无效,划不动屏幕,但是代码逻辑都有执行到。 scrollIntoView也无效。 原因:这是因为 iOS 的触摸事件处理机制和 touch-action: none 的设置有关。ios有太多得交互动作,从而会影响…...
springboot整合VUE之在线教育管理系统简介
可以学习到的技能 学会常用技术栈的使用 独立开发项目 学会前端的开发流程 学会后端的开发流程 学会数据库的设计 学会前后端接口调用方式 学会多模块之间的关联 学会数据的处理 适用人群 在校学生,小白用户,想学习知识的 有点基础,想要通过项…...
Mysql8 忘记密码重置,以及问题解决
1.使用免密登录 找到配置MySQL文件,我的文件路径是/etc/mysql/my.cnf,有的人的是/etc/mysql/mysql.cnf 在里最后加入 skip-grant-tables重启MySQL服务 service mysql restartShutting down MySQL… SUCCESS! Starting MySQL… SUCCESS! 重启成功 2.登…...
C# 表达式和运算符(求值顺序)
求值顺序 表达式可以由许多嵌套的子表达式构成。子表达式的求值顺序可以使表达式的最终值发生 变化。 例如,已知表达式3*52,依照子表达式的求值顺序,有两种可能的结果,如图9-3所示。 如果乘法先执行,结果是17。如果5…...
