Vue常用自定义指令、纪录篇

文章目录

    • 一、元素尺寸发生变化时
    • 二、点击元素外自定义指令
    • 三、元素拖拽自定义指令
    • 四、防抖自定义指令
    • 五、节流自定义指令
    • 六、权限判断自定义指令

一、元素尺寸发生变化时

使用场景:
当元素的尺寸发生变化时需要去适配一些元素时。
或者在元素尺寸发生变化时要去适配ECharts
等多种场景,完整代码如下

<!-- Vue3写法 -->
<template><div class="resize"><div class="box" v-resize="onResize"></div></div>
</template><script setup lang="ts">// 监听元素大小变化的指令
const map = new WeakMap()
const ob = new ResizeObserver((entries) => {for (const entry of entries) {// 获取dom元素的回调const handler = map.get(entry.target)//存在回调函数if (handler) {// 将监听的值给回调函数handler({width: entry.borderBoxSize[0].inlineSize,height: entry.borderBoxSize[0].blockSize})}}
})const vResize = {mounted(el: any, binding: any) {//将dom与回调的关系塞入mapmap.set(el, binding.value)//监听el元素的变化ob.observe(el)},unmounted(el: any) {//取消监听ob.unobserve(el)}
}function onResize() {console.log("元素的大小发生了改变")
}
</script><style scoped lang="scss">
.resize {width: 80%;margin: 200px auto 0px;.box {margin-top: 50px;width: 100%;height: 200px;border: 1px solid #000;}
}
</style>

二、点击元素外自定义指令

使用场景:
下拉菜单:当用户点击下拉菜单或模态窗口外部区域时,关闭下拉菜单或模态窗口。
上下文菜单:在右键打开的上下文菜单中,当用户点击菜单外的其他地方时,关闭上下文菜单。
等多种场景,完整代码如下

<template><div class="clickoutside"><div class="button" @click.self="buttonClick" v-clickoutside="buttonClickoutside"> 就当是个按钮<div class="inner" :class="dropdownVisible ? 'dropdownOpen' : ''"></div></div></div>
</template><script setup lang="ts">
import { ref } from 'vue'const vClickoutside = {mounted(el: any, bindings: any) {el.clickOutsideEvent = (event: any) => {// 判断点击是否发生在 el 外部if (!(el === event.target || el.contains(event.target))) {// 如果是,调用绑定的方法bindings.value();}};document.addEventListener('click', el.clickOutsideEvent);},unmounted(el: any) {// 移除事件监听document.removeEventListener('click', el.clickOutsideEvent);},
}
const dropdownVisible = ref(false)function buttonClick() {dropdownVisible.value = !dropdownVisible.value
}function buttonClickoutside() {dropdownVisible.value = falseconsole.log("点击了外面")
}
</script><style scoped lang="scss">
.clickoutside {width: 80%;margin: 200px auto 0px;.button {background: #409EFF;width: 160px;text-align: center;height: 44px;line-height: 44px;border-radius: 4px;color: #fff;cursor: pointer;position: relative;.inner {top: 54px;width: 100%;height: 0px;transition: 0.3s;position: absolute;background: red;}.dropdownOpen {height: 200px;}}
}
</style>

点击按钮时弹出红色区域,再次点击按钮或者按钮外部区域时收起红色区域。
在这里插入图片描述

三、元素拖拽自定义指令

使用场景:
允许用户自由拖拽组件、窗口、等其他元素
各个场景不同,根据自己需求来。
完整代码如下:

<template><div class="drag"><div class="box" v-drag></div></div>
</template><script setup lang="ts">const vDrag = {mounted(el: any) {let active = false; // 拖拽状态let currentX = 0; // 当前鼠标的 X 坐标let currentY = 0; // 当前鼠标的 Y 坐标let initialX = 0; // 初始鼠标按下时相对于元素的 X 偏移量let initialY = 0; // 初始鼠标按下时相对于元素的 Y 偏移量el.addEventListener("mousedown", (e: any) => {// 元素鼠标按下事件// 记录初始鼠标按下时相对于元素的偏移量initialX = e.clientX - el.offsetLeftinitialY = e.clientY - el.offsetTopactive = true; // 设置为正在拖拽状态})document.addEventListener("mouseup", () => {active = false;  // 鼠标抬起,结束拖拽状态})document.addEventListener("mousemove", (e: any) => {// 处于正在拖拽时if (active) {currentX = e.clientX - initialX; // 计算当前鼠标相对于初始的 X 坐标currentY = e.clientY - initialY; // 计算当前鼠标相对于初始的 Y 坐标const x = Math.max(0, Math.min(currentX, window.innerWidth - el.offsetWidth)); // 限制 X 坐标范围const y = Math.max(0, Math.min(currentY, window.innerHeight - el.offsetHeight));// 限制 Y 坐标范围el.style.left = `${x}px`; // 设置元素的 left 位置el.style.top = `${y}px`; // 设置元素的 top 位置}})},
}</script><style scoped lang="scss">
.drag {.box {width: 150px;height: 150px;position: fixed;cursor: pointer;border-radius: 6px;background: #409EFF;}
}
</style>

在这里插入图片描述

四、防抖自定义指令

使用场景:
当用户重复点击按钮时,在1秒再次点击不会触发提交,只有超过一秒并且没有新的点击才会触发提交
输入框输入等可能存在频繁触发的场景
完整代码如下:

<template><div class="debounce"><div class="button" v-debounce-directive="debounceDirective">登 录</div></div>
</template><script setup lang="ts">const vDebounceDirective = {mounted(el: any, binding: any) {// 将元素的事件处理函数替换为防抖后的函数// binding.value 是传入的 debounceDirective 方法el.addEventListener(binding.arg || 'click', debounce(binding.value, 1000));},// 在指令从元素移除时调用unmounted(el: any, binding: any) {el.removeEventListener(binding.arg || 'click', binding.value);},
}function debounceDirective() {console.log("哈哈哈")
}// 防抖函数
const debounce = (fn: Function, delay: number) => {let timer = null as any;return function (...args: any[]) {// 清除之前的定时器if (timer) {clearTimeout(timer);}// 设置新的定时器,延迟后执行函数timer = setTimeout(() => {fn(...args);}, delay);};
};</script><style scoped lang="scss">
.debounce {width: 800px;margin: 200px auto 0px;.button {width: 120px;height: 44px;line-height: 44px;text-align: center;color: #fff;background: #409EFF;border-radius: 4px;cursor: pointer;}
}
</style>

五、节流自定义指令

使用场景
节流有很多种实现发放,通常都是根据不同的应用场景使用不同的方法。

<template><div class="throttle" v-throttle="handleScroll">滚动区域</div>
</template><script setup lang="ts">const handleScroll = () => {// 这里处理滚动相关逻辑console.log('滚动事件触发');
};const vThrottle = {mounted(el: any, binding: any) {// 给元素添加节流处理后的事件监听window.addEventListener('scroll', throttle(binding.value, 5000));},// 指令卸载时unmounted(el: any, binding: any) {window.removeEventListener(binding.arg || 'scroll', binding.value);},
}/*** 节流函数* @param {Function} fn 要执行的函数* @param {number} delay 节流时间间隔(毫秒)* @returns {Function} 节流处理后的函数*/
const throttle = (fn: Function, delay: number) => {let lastCallTime = 0;return function (...args: any[]) {const currentTime = new Date().getTime();if (currentTime - lastCallTime > delay) {fn.apply(this, args);lastCallTime = currentTime;}};
};</script><style scoped lang="scss">
.throttle {height: 30000px;
}
</style>

六、权限判断自定义指令

使用场景:
在后台管理项目中,通常我们会根据用户所拥有的权限去限制该用户有哪些操作按钮
下面来举个例子,对于单个按钮权限的判断和按钮组权限判断
完整代码如下:

单按钮在这里就不用多说什么了。
在这里插入图片描述
在这里插入图片描述
可能会有人不理解按钮组判断了个寂寞。
举个简单的例子,比如说我们用到表格组件,用户A有操作权限则显示表格后面的操作列,用户B没有任何操作时,我们大可没有必要在显示操作列,对就这么简单。
在这里插入图片描述
在这里插入图片描述

<template><div class="hasbtn" v-has-all="'add,edit,delete,see,upload,download'"><div class="btn" v-has="'add'">新增</div><div class="btn" v-has="'edit'">编辑</div><div class="btn" v-has="'delete'">删除</div><div class="btn" v-has="'see'">查看</div><div class="btn" v-has="'upload'">上传</div><div class="btn" v-has="'download'">下载</div></div>
</template><script setup lang="ts">
import { reactive, toRefs, onMounted } from "vue";const state = reactive({userPower: ['add', 'edit'], // 模拟用户所拥有的权限admin: false, // 该用户是否是超级管理员
})
const { } = toRefs(state)onMounted(() => {})// 判断单个按钮权限方法
const hasPermission = (userPermission: any) => {let permissionList = state.userPowerreturn permissionList.some((i: any) => i == userPermission)
};
// 判断单个按钮权限指令
const vHas = {mounted(el: any, binding: any) {if (state.admin) { // 当用户是超级管理时,拥有所有按钮的权限return true} else {if (!hasPermission(binding.value)) {// 如果用户没有某个权限移除改元素el.parentNode.removeChild(el);}}},
}// 判断按钮组权限方法
const hasAllPermission = (userPermission: any) => {let data = userPermission.split(",")return hasOneItemInCommon(data, state.userPower)
}
// 判断按钮组权限指令
const vHasAll = {mounted(el: any, binding: any) {if (state.admin) { // 当用户是超级管理时,拥有所有按钮的权限return true} else {if (!hasAllPermission(binding.value)) {// 如果用户没有某个权限移除改元素el.parentNode.removeChild(el);}}},
}const hasOneItemInCommon = (arr1: any, arr2: any) => {for (const item of arr2) {if (arr1.includes(item)) {return true;}}return false;
};
</script><style scoped lang="scss">
.hasbtn {display: flex;align-items: center;justify-content: center;.btn {width: 120px;height: 44px;line-height: 44px;text-align: center;color: #fff;background: #409EFF;border-radius: 4px;cursor: pointer;margin-right: 20px;}
}
</style>

工作中如遇到新的自定义指令会继续补充。

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

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

相关文章

TiDB学习9:Ti Cloud简介

目录 1. 为什么选择TiDB 2. 多租户 3. TiDB架构 4. 什么是TiDB Cloud 5. TiDB Cloud Provider Region 6. TiDB Cloud 入门 6.1 在浏览器中打开TiDB Cloud 6.2 创建您的账户 6.3 Developer Tier 与Dedicated Tier 6.3.1 Developer Tier 6.3.2 Dedicated Tier 6.3.2.…

[HUBUCTF 2022 新生赛]RSAaaa

题目&#xff1a; EXP 就你小子是黑客&#xff1f; 我忘记怎么解密了&#xff01; 靠你了&#xff0c;大黑阔&#xff01;(536970330703, 65537) message: 473878130775 40132555282 40132555282 94619939727 72818765591 208015808884 42561234694 159353248388 27748063975 1…

逆天工具一键修复图片,视频去码。简直不要太好用!

今天&#xff0c;我要向您推荐一款功能强大的本地部署软件&#xff0c;它能够在您的计算机上一键修复图片和视频&#xff0c;去除令人不悦的码赛克&#xff08;轻度马赛克&#xff09;。这款软件是开源的&#xff0c;并在GitHub上公开可用&#xff0c;您可以免费下载并使用。 …

vector的功能讲解与底层实现

本文主要介绍vector的内容以及使用和模拟实现。 vector在英文翻译中是矢量的意思&#xff0c;但在c中他的本质是一个顺序表&#xff08;容器&#xff09;&#xff0c;是一个类模板&#xff0c;&#xff08;用模板创建变量就要参考我们之前的实例化内容了&#xff09;用可以改变…

dnsrecon一键开始负载平衡检测(KALI工具系列十四)

目录 1、KALI LINUX简介 2、lbd工具简介 3、在KALI中使用lbd 3.1 测试目标域名是否存在负载不平衡 4、总结 1、KALI LINUX简介 Kali Linux 是一个功能强大、多才多艺的 Linux 发行版&#xff0c;广泛用于网络安全社区。它具有全面的预安装工具和功能集&#xff0c;使其成为…

TCP协议详解及其相关的10个核心机制(面试重点)

TCP协议的报文格式 TCP协议有连接&#xff0c;可靠性传输&#xff0c;面向字节流&#xff0c;全双工。 他的数据格式如图&#xff1a; 根据他的数据格式&#xff0c;在这里我们只知道 16位源端口号&#xff08;表示客户端这里的端口号&#xff09;&#xff0c;16位目的端口号&…

算法简单笔记4

5月31号&#xff0c;明天决赛&#xff0c;今天脑子也是一滩浆糊&#xff0c;踏马的一道题也做不出来&#xff0c;超级难受&#xff0c;只好简单复盘一下两道之前的题目&#xff0c;看完就差不多了&#xff0c;再学也没啥用了&#xff0c;写完这两题题解我就回去打把steam绝地求…

深度学习聚类再升级!新算法实现强悍性能,准确率超98%

深度聚类不仅继承了传统聚类算法的优点&#xff0c;在对高维和非线性数据的处理能力&#xff0c;以及自适应性和抗噪性方面也具有很大优势。 具体来说&#xff0c;结合深度学习的聚类算法通过利用深度神经网络的强大特征提取能力&#xff0c;自动学习和识别数据中的复杂结构和…

全志H616(BIGTREETECH CB1)和 博通BCM2711(树莓派4B)CPU对比测试

一&#xff0c;实物对比图&#xff1a; BIGTREETECH CB1的底板接口的分布和树莓派4B是一样的&#xff0c;但是没有树莓派的音频接口&#xff0c;底板也不能放到树莓派4B的官方外壳里&#xff0c;因为底板的背面有一个DSI接口&#xff0c;高度超出了。 二&#xff0c;开发板硬…

HBSL-22Q/K定时限过电流继电器 板前接线 JOSEF约瑟

HBSL系列静态定时限过电流继电器 系列型号&#xff1a; HBSL-11A/E静态定时限过电流继电器&#xff1b;HBSL-11A/K静态定时限过电流继电器&#xff1b;HBSL-12A/E静态定时限过电流继电器&#xff1b; HBSL-12A/K静态定时限过电流继电器&#xff1b;HBSL-21A/E静态定时限过电…

JS-09-es6常用知识1

目录 1 模板字符串 1.1 模板字符串基本用法 1.2 模板字符串解决了一些痛点 2 解构赋值 2.1 对象的解构赋值 2.2 函数参数的解构赋值 2.3 补写&#xff1a;属性的简写 3 rest参数 3.1 arguments 3.2 rest参数 3.3 补充&#xff1a;判断数据类型 4 箭头函数 4.1 …

SpringBoot-世界杯足球赛网站-28567

Springboot世界杯足球赛网站 摘 要 信息化社会内需要与之针对性的信息获取途径&#xff0c;但是途径的扩展基本上为人们所努力的方向&#xff0c;由于站在的角度存在偏差&#xff0c;人们经常能够获得不同类型信息&#xff0c;这也是技术最为难以攻克的课题。针对世界杯足球赛…

jsmug:一个针对JSON Smuggling技术的测试PoC环境

关于jsmug jsmug是一个代码简单但功能强大的JSON Smuggling技术环境PoC&#xff0c;该工具可以帮助广大研究人员深入学习和理解JSON Smuggling技术&#xff0c;并辅助提升Web应用程序的安全性。 背景内容 JSON Smuggling技术可以利用目标JSON文档中一些“不重要”的字节数据实…

C++ 特殊运算符

一 赋值运算符 二 等号作用 三 优先级和结合顺序 四 左值和右值 五 字节数运算符 条件运算符 使用条件运算符注意 逗号运算符 优先级和结合顺序 总结

实战15:bert 命名实体识别、地址解析、人名电话地址抽取系统-完整代码数据

直接看项目视频演示: bert 命名实体识别、关系抽取、人物抽取、地址解析、人名电话地址提取系统-完整代码数据_哔哩哔哩_bilibili 项目演示: 代码: import re from transformers import BertTokenizer, BertForTokenClassification, pipeline import os import torch im…

【linux】docker下nextcloud安装人脸识别插件2

接上文 【linux】docker下nextcloud安装人脸识别插件-CSDN博客 由于作者不再维护此插件&#xff0c;转而开发新的插件 recognize &#xff0c;因此同步更新插件使用教程。 1、下载人脸识别app&#xff1a;recognize Recognize - Apps - App Store - Nextcloud 2、将插件recog…

Java解析JSON并修改属性值:从JSON到JsonObject的逐层解析

哈喽&#xff0c;大家好&#xff0c;我是木头左&#xff01; 在Java中&#xff0c;可以使用各种库来解析和操作JSON数据。其中&#xff0c;Gson和Jackson是两个非常流行且功能强大的库。在这篇文章中&#xff0c;将使用Gson库来解析给定的JSON字符串&#xff0c;修改operationB…

python移位操作符(左移位操作符<<、右移位操作符>>)(允许开发者对整数进行位操作,乘2或除2)(左移操作、右移操作)(位掩码操作|=)

文章目录 Python 中的移位操作符详解移位操作符简介左移位操作符 (<<)语法和使用示例代码输出 右移位操作符 (>>)语法和使用示例代码输出 移位操作符的应用场景快速乘除运算&#xff1a;使用移位操作符代替传统的乘法和除法运算&#xff0c;可以提高计算速度。位掩…

生产问题(十六)数据丢失-mysql binlog排查

一、引言 最近作者遇到一个线上问题&#xff0c;是mysql 的数据丢失了&#xff0c;这里记录一下排查过程和binlog的分析。 二、问题 问题出现的表象是应用系统大量报错&#xff0c;各种空指针之类的&#xff0c;这种一看就不可能是代码发布的问题&#xff0c;原因一定在框架、…

第十八节:认识一些经典递归过程

一 暴力递归就是尝试 1&#xff0c;把问题转化为规模缩小了的同类问题的子问题 2&#xff0c;有明确的不需要继续进行递归的条件(base case) 3&#xff0c;有当得到了子问题的结果之后的决策过程 4&#xff0c;不记录每一个子问题的解 二 打印n层汉诺塔从最左边移动到最右边的全…