Vue 自定义指令
文章目录
- 注册
- 局部注册
- 全局注册
- 钩子
- 钩子参数
- 应用
- 1、按钮权限验证
- 2、自定义用户行为收集指令
- 3、按钮点击防抖
- 4、输入框自动获取焦点
- 5、输入框自动去空字符串
- 6、文字展示不下时展示提示框
注册
局部注册
export default {setup() {/*...*/},directives: {// 在模板中启用 v-focusfocus: {/* ... */}}
}
全局注册
const app = createApp({})// 使 v-focus 在所有组件中都可用
app.directive('focus', {/* ... */
})
钩子
const myDirective = {// 在绑定元素的 attribute 前// 或事件监听器应用前调用created(el, binding, vnode) {// 下面会介绍各个参数的细节},// 在元素被插入到 DOM 前调用beforeMount(el, binding, vnode) {},// 在绑定元素的父组件// 及他自己的所有子节点都挂载完成后调用mounted(el, binding, vnode) {},// 绑定元素的父组件更新前调用beforeUpdate(el, binding, vnode, prevVnode) {},// 在绑定元素的父组件// 及他自己的所有子节点都更新后调用updated(el, binding, vnode, prevVnode) {},// 绑定元素的父组件卸载前调用beforeUnmount(el, binding, vnode) {},// 绑定元素的父组件卸载后调用unmounted(el, binding, vnode) {}
}
钩子参数
指令的钩子会传递以下几种参数:
- el:指令绑定到的元素。这可以用于直接操作 DOM。
- binding:一个对象,包含以下属性。
- value:传递给指令的值。例如在 v-my-directive=“1 + 1” 中,值是 2。
- oldValue:之前的值,仅在 beforeUpdate 和 updated 中可用。无论值是否更改,它都可用。
- arg:传递给指令的参数 (如果有的话)。例如在 v-my-directive:foo 中,参数是 “foo”。
- modifiers:一个包含修饰符的对象 (如果有的话)。例如在 v-my-directive.foo.bar 中,修饰符对象是 { foo: true, bar: true }。
- instance:使用该指令的组件实例。
- dir:指令的定义对象。
- vnode:代表绑定元素的底层 VNode。
- prevVnode:代表之前的渲染中指令所绑定元素的 VNode。仅在 beforeUpdate 和 updated 钩子中可用。
应用
1、按钮权限验证
功能描述: 项目根据登录用户所配置的角色权限,对按钮进行权限控制,拥有权限的按钮才能够触发点击事件,没有权限的按钮触发时进行提示。
/*** # 验证用户权限, 并进行提示** @example* ```vue* <el-button* v-auth="{* code: AuthCode.UPLOAD_FILE,* name: AuthName.UPLOAD_FILE,* event: handleUploadConfirm,* projectId* }"* >* 确认上传* </el-button>* ```** @param code 权限 code* @param name 权限对应中文名* @param event 权限验证通过后要执行的函数* @param projectId? 可选, 项目 id* @param type 两种验证模式 'project' | 'role' 如果是 role, 则通过默认角色权限进行判断, 如果是 project, 则通过项目权限进行判断*/
export default <Directive>{mounted(el: HTMLElement, bindings) {if (!bindings.value) {throw new Error('value 不能为空')}if (typeof bindings.value !== 'object') {throw new Error('value 必须为对象')}const {code,name,event,type,projectId,bindEvent = 'click'} = bindings.valueel.addEventListener(bindEvent, () => {if (!checkAuth(code, name, projectId, type)) {return}if (typeof event === 'function') {event()}})}
}/*** @param code 权限 code* @param name 权限名称* @param projectId 项目 id* @param type 两种验证模式 'project' | 'role' 如果是 role, 则通过默认角色权限进行判断, 如果是 project, 则通过项目权限进行判断* @returns*/
function checkAuth(code?: string,name?: string,projectId?: string,type = 'project'
) {if (!code) {throw new Error('权限名称不能为空')}const userStore = useUserStore()let auth = falseif (type === 'project' && projectId) {auth = checkProject(code, projectId)} else if (type === 'role') {auth = checkRole(code)}if (!auth) {// 用户没有该权限ElMessage.warning(`您没有 ${name} 权限,无法执行该操作!`)return false}return true
}function checkProject(code: string, projectId: string) {...
}function checkRole(code: string) {...
}
2、自定义用户行为收集指令
功能描述:需要对项目中用户的行为进行收集,以备后续的日志记录查询或者用户行为分析。 比如记录哪个用户,在什么时间,在哪个页面,触发了什么功能。支持按钮按钮行为收集、非按钮点击行为收集。
/*** @example* <el-link* type="primary"* v-collect* @click="getRoleAuthList(row)"* >* 查看* </el-link>* * <el-button* size="large"* type="primary"* v-collect* @click="handleClickMove"* >* 新增项目* </el-button>* * 自定义用户行为收集指令*/
export default <Directive>{mounted(el: HTMLElement, bindings) {// 可以根据当前路由转换得到中文的页面const pathname = window.location.pathnameconst userInfo = getUserInfo()el.addEventListener('mousedown', e => {e.stopPropagation()const collect = getCollect()const path: string = bindings.value || (el.textContent as string)let name = (path?.trim())?.trim() || ''if (name.startsWith('/')) {name = name.slice(1)}collect.push({userId: userInfo.id,operateTime: getTime(),page: pathname,operateName: name})setCollect(collect)})}
}const collectKey = 'USER_SELECT'
function getCollect(): Collect[] {const collect = window.localStorage.getItem(collectKey) || '[]'return JSON.parse(collect)
}function setCollect(collect: Collect[]) {window.localStorage.setItem(collectKey, JSON.stringify(collect))
}
3、按钮点击防抖
功能描述:点击按钮进行操作时,防止用户短时间点击多次触发多次事件,为按钮点击事件添加防抖功能,默认 1 秒以内重复点击无效。实现方案是点击按钮触发一次事件,给按钮设置 disabaled 属性为 true,1 秒后删除该限制。
/*** @example* <el-button v-clicked:500></el-button>* * @param delay number类型, 设置禁止点击的时间间隔, 默认1000*/export default {mounted(el: HTMLElement | HTMLButtonElement, bindings: DirectiveBinding) {let timer: number | null = nulllet delay = 1000const oldEvents = el.style.pointerEventsif (bindings.arg) {if (!/^\d+$/.test(bindings.arg)) {throw new Error('参数必须是数字')}delay = Number(bindings.arg)}el.addEventListener('click', setDisabled)function setDisabled() {el.setAttribute('disabled', 'true')// el.classList.add('is-disabled')if (el.tagName !== 'BUTTON') {el.style.pointerEvents = 'none' // 点击不到按钮,穿透到下层元素}if (timer) {window.clearTimeout(timer)timer = null}timer = window.setTimeout(() => {// el.classList.remove('is-disabled')el.removeAttribute('disabled')el.style.pointerEvents = oldEvents}, delay)}}
}
4、输入框自动获取焦点
功能描述:页面加载之后自动聚焦到某个输入框,使输入框处于输入状态
/**
* @example
* <el-input v-focus></el-input>
*/
export default {mounted(el: HTMLElement | HTMLInputElement) {let ipt: HTMLInputElement | nullif (el.nodeName === 'INPUT') {ipt = el as HTMLInputElement} else {ipt = el.querySelector('.el-input__inner') as HTMLInputElement}ipt && (ipt as HTMLInputElement).focus()}
}
5、输入框自动去空字符串
interface HTMLElementPlus extends HTMLElement {_handler: (e: KeyboardEvent) => void_ele: HTMLElementPlus
}
export default {mounted(el: HTMLElementPlus) {let iptif (el.nodeName === 'INPUT') {ipt = el} else {ipt = el.querySelector('.el-input__inner')}const handler = (e: KeyboardEvent) => {if (e.code === 'Space') {e.preventDefault()}}el._ele = ipt as HTMLElementPlusel._handler = handler;(ipt as HTMLElementPlus).addEventListener('keydown', handler)},unmounted(el: HTMLElementPlus) {const { _ele } = el_ele.removeEventListener('keydown', _ele._handler)}
}
6、文字展示不下时展示提示框
功能描述:项目里经常有一些列表有展示性文字,有的项文字展示的全有的项文字展示不全,如果简单粗暴的添加提示文字会使得展示全的文字也有提示文字,不太友好。通过该自定义指令,只对展示不全的文字添加文字提示。
/*** 根据字符长度控制 el-tooltip 的显隐* 1.单行文本使用:需在对应组件定义moveTodisabled* 例:* const moveTodisabled = ref({disablesd: true})* <el-tooltip:content="item.name":disabled="moveTodisabled"><div v-tooltip="moveTodisabled">{{ item.name }}</div></el-tooltip>*//*** 2.列表使用, 参数: list,index(当前索引)例:<el-option v-for="(item, index) in fileNameList" :key="item.id" :label="item.name" :value="item.name"><el-tooltip:content="item.name":disabled="item.moveTodisabled"><div v-tooltip:[index]="fileNameList" class="custom-dropdown-item">{{ item.name }}</div></el-tooltip></el-option>*/
interface Actual {width: numberelement: HTMLSpanElement
}
interface HTMLElementPlus extends HTMLElement {_handler: () => void_handler2: () => void_ele: HTMLElementPlus_ele_temp: HTMLSpanElement | null
}function getActualWidth(text: string, fontSize: string): Actual {const span: HTMLSpanElement = document.createElement('span')span.innerText = textspan.style.cssText ='visibility:hidden;position:absolute;z-index:-1;top:0;font-size:' + fontSizedocument.body.appendChild(span)const rect = span.getBoundingClientRect()// offsetWidth 是整数return { width: Math.round(rect.width), element: span }
}function destoryEle(ele: HTMLSpanElement) {ele.parentNode?.removeChild(ele)
}export default {mounted(el: HTMLElementPlus, binding: DirectiveBinding) {const handler = () => {const fontSize = getComputedStyle(el, null).fontSizeconst { width, element }: Actual = getActualWidth(el.innerText, fontSize)el._ele_temp = element as HTMLSpanElementif (el.offsetWidth < width) {if (!isNaN(index)) {binding.value[index].moveTodisabled = false} else {binding.value.disabled = false}} else {if (!isNaN(index)) {binding.value[index].moveTodisabled = true} else {binding.value.disabled = true}}}const handle2 = () => {destoryEle(el._ele_temp as HTMLSpanElement)el._ele_temp = null}el._handler = handlerel._handler2 = handle2el._ele = elel.addEventListener('mouseenter', handler)el.addEventListener('mouseout', handle2)},unmounted(el: HTMLElementPlus) {const { _ele } = el_ele.removeEventListener('mouseenter', _ele._handler)_ele.removeEventListener('mouseout', _ele._handler2)}
}
相关文章:

Vue 自定义指令
文章目录 注册局部注册全局注册 钩子钩子参数应用1、按钮权限验证2、自定义用户行为收集指令3、按钮点击防抖4、输入框自动获取焦点5、输入框自动去空字符串6、文字展示不下时展示提示框 注册 局部注册 export default {setup() {/*...*/},directives: {// 在模板中启用 v-fo…...

【python】python图书管理系统_普通用户+管理员菜单(源码+论文)【独一无二】
👉博__主👈:米码收割机 👉技__能👈:C/Python语言 👉公众号👈:测试开发自动化【获取源码商业合作】 👉荣__誉👈:阿里云博客专家博主、5…...

智能路面裂缝检测:基于YOLO和深度学习的全流程实现
引言 路面裂缝检测是维护道路质量和延长道路寿命的重要手段。传统的检测方法往往费时费力且易受人为因素影响。为了提高检测效率和准确性,本文介绍了一种基于深度学习的路面裂缝检测系统。该系统包括用户界面,利用YOLO(You Only Look Once&a…...
C++ unordered_map
1. unordered系列关联式容器 在C98 中, STL 提供了底层为红黑树结构的一系列关联式容器,在查询时效率可达到 ,即最差情况下需要比较红黑树的高度次,当树中的节点非常多时,查询效率也不理想。最好的查询是,…...

PHP Switch 语句
PHP 中的 switch 语句是一种多路分支语句,它允许一个变量的值对多个代码块进行选择执行。这通常比使用多个 if...elseif...else 语句更清晰、更易于维护。下面将详细介绍 PHP 中 switch 语句的使用方法。 基本语法 switch (n) {case label1:// 如果 n label1&…...

electron 网页TodoList应用打包win桌面软件数据持久化
参考: electron 网页TodoList工具打包成win桌面应用exe https://blog.csdn.net/weixin_42357472/article/details/140648621 electron直接打包exe应用,打开网页上面添加的task在重启后为空,历史没有被保存,需要持久化工具保存之前…...

软件缺陷(Bug)、禅道
目录 软件缺陷的判定标准 软件缺陷的核心内容 构成缺陷的基本要素 缺陷报告 缺陷管理 缺陷的跟踪流程 项目管理工具--禅道 软件在使用过程中存在的任何问题(如:错误、异常等),都叫软件的缺陷,简称bug。 软件缺…...

MySQL客户端命令一节将.sql文件导入MySQL
MySql客户端命令 直接输入SQL语句 使用MySQL客户端连接到服务器之后,可以发送SQL语句到服务器执行,并且以;和\g, \G作为结束不同的结束方式显示内容有所不同** TIPS: ;和\g结尾以表格的形式显示结果\G以行的形式显示结果 在连接到服务器之后…...

[论文笔记] DCA(Dual Chunk Attention)
DCA(Dual Chunk Attention)是一种在自然语言处理模型中用来处理长文本的技术。传统的注意力机制(Attention)在处理长文本时可能会遇到效率和性能瓶颈,因为计算每个单词与其他所有单词之间的关系会随着文本长度的增加而…...

构建查询洞察 UI
本文字数:2631;估计阅读时间:7 分钟 作者:Bucky Schwarz 本文在公众号【ClickHouseInc】首发 我们最近发布了 Query Insights 的初步实现,为 ClickHouse Cloud 用户提供了一种便捷的方法来查看和解释查询日志。该功能对…...

【北京迅为】《i.MX8MM嵌入式Linux开发指南》-第三篇 嵌入式Linux驱动开发篇-第五十九章 等待队列
i.MX8MM处理器采用了先进的14LPCFinFET工艺,提供更快的速度和更高的电源效率;四核Cortex-A53,单核Cortex-M4,多达五个内核 ,主频高达1.8GHz,2G DDR4内存、8G EMMC存储。千兆工业级以太网、MIPI-DSI、USB HOST、WIFI/BT…...

35.【C语言】详解函数递归
目录: 定义 作用 例子1~3 拓展学习 趣味练习 1.定义:函数自己调用自己(递推回归) int main() {main()return 0; } 这样容易死循环,导致爆栈(Stack Overflow) 所以需要设立限制条件,使执行时越来越接近条…...

【机器学习】智驭未来:机器学习如何重塑制造业的转型与升级
📝个人主页🌹:Eternity._ 🌹🌹期待您的关注 🌹🌹 ❀目录 🔍1. 引言📒2. 机器学习重塑制造业生产流程🌸预测性维护:减少停机时间,提高设…...

Python爬虫(5) --爬取网页视频
文章目录 爬虫爬取视频指定url发送请求UA伪装请求页面 获取想要的数据解析定位定位音视频位置 存放视频完整代码实现总结 爬虫 Python 爬虫是一种自动化工具,用于从互联网上抓取网页数据并提取有用的信息。Python 因其简洁的语法和丰富的库支持(如 requ…...

【Unity】关于Luban的简单使用
最近看了下Luban导出Excel数据的方式,来记录下 【Unity】关于Luban的简单使用 安装Luban开始使用UnityLubanC# 扩展 安装Luban Luban文档:https://luban.doc.code-philosophy.com/docs/beginner/quickstart 1.安装dotnet sdk 8.0或更高版本sdk 2.githu…...

企业公户验证API如何使用JAVA、Python、PHP语言进行应用
在纷繁复杂的金融与商业领域,确保每笔交易的安全与合规是至关重要的。而企业公户验证API,正是这样一位默默守护的数字卫士,它通过智能化的手段,简化了企业对公账户验证流程,让繁琐的审核变得快捷且可靠。 什么是企业公…...

杰发科技Bootloader(2)—— 基于7840的Keil配置地址
序 在7840的sample代码里面有一个简单的Boot跳转APP的示例 PFlash地址从0开始 DFlash的地址从1000000开始 Boot解析 他的boot地址配置为0 Boot的代码主要是这几行,主要作用就是Flash的跳转 int main(void) {SystemClock_Config();InitDebug();printf("demo…...

cmd常用命令
在Windows操作系统中,CMD(Command Prompt)是一个强大的命令行工具,允许用户通过键入命令来执行各种系统级操作。以下是一些常用的CMD命令及其功能: 文件与目录管理 dir:显示当前目录下的文件和子目录列表。…...

PCIe 以太网芯片 RTL8125B 的 spec 和 Linux driver 分析备忘
1,下载 RTL8125B driver 下载页: https://www.realtek.com/Download/List?cate_id584 2,RTL8125B datasheet下载 下载页: https://file.elecfans.com/web2/M00/44/D8/poYBAGKHVriAHnfWADAT6T6hjVk715.pdf3, 编译driver 解压: $ tar xj…...

Python tkinter Menu菜单组件详解
好久没有更新了,今天我来领大家熟悉一下Menu组件 1.认识、了解Menu 什么是Menu menu组件是tkinter中的菜单组件,通过该组件,开发者可以为窗口设计菜单和工具栏等。(ttk还提供了treeview树形菜单,python遍历目录的两种…...

谷粒商城实战笔记-46-商品服务-API-三级分类-配置网关路由与路径重写
文章目录 一,准备工作1,新增一级菜单2,新增二级菜单 二,前端树形界面开发1,开发分类展示组件 三,远程调用接口获取商品分类数据1,远程调用2,路由配置 错误记录 本节的主要内容&#…...

简要了解sql注入
sql注入安全测试中危害 数据库中的数据,对数据库数据进行操作(查询、删除等);网站的权限,找到注入点后可后门写入; sql注入产生原理详细分析 可控变量,带入数据库查询,变量未存在…...

Java 扫雷游戏
程序分析 使用Java编写的扫雷游戏界面程序,主要内容总结如下: Frame类继承自JFrame,构建了扫雷游戏的界面。 包含文本框text、标签nowBomb和setBomb、按钮start、面板MenuPamel和bombPanel等组件。通过jbInit方法进行初始化设置,…...

vue3 命令运行窗口暴露网络地址,以及修改端口号
一般情况下这里的地址是隐藏的 这里加上 --host 可以暴露网络地址,再加上--port --8080 就可以将端口号修改为8080(修改后边的数字就可以修改为你想要的端口号)...

由CANoe自带协议栈在TCP断开连接时同时发送两条FIN报文引起的注意事项
在我写这篇文章CAPL如何在底层模拟TCP Server端断开TCP连接时,我发现了一个奇怪的现象。我为了使用CAPL组装报文的方式实现TCP Server断开连接的过程,插入一个网络节点作为Client端。为了让Client能够发起连接和发起断开连接,给网络节点配置了独立的TCP/IP Stack,也就是CAN…...

FastGPT部署和接入使用重排模型bce-reranker-base
bce-reranker简介 bce-reranker 是一种专门用于信息检索和自然语言处理领域中的重排序(reranking)模型。这种模型由北京智源人工智能研究院(BAAI)开发,是 BGE(BAAI General Embedding)系列的一部分。BGE 系列模型专注于提供通用的嵌入表示,而 bce-reranker 则更进一步…...

Android笔试面试题AI答之线程Handler、Thread(2)
答案仅供参考,来自 讯飞星火大模型 目录 1.Android多线程间通信和多进程之间通信有什么不同,分别怎么实现?2.请解释下在单线程模型中Message、Handler、Message Queue、Looper之间的关系?3.Android 线程间通信有哪几种方式?4.子线程发消息…...

某某物联rabbitmqhttp二轮充电桩协议充电协议对接
对接方式概述: 1)请求采用 http 协议方式,推送数据采用 amqp(默认 rabbitmq)点对点消息队 列方式。 2)消息队列连接信息,需贵方完善。 1 hostIp: 2 virtualHost: 3 userName: 4 pass…...

黑马JavaWeb企业级开发(知识清单)03——HTML实现正文:排版(音视频、换行、段落)、布局标签(div、span)、盒子模型
文章目录 前言一、正文排版1. 视频标签: < video >2. 音频标签: < audio >3. 换行标签: < br >4. 段落标签 < p >5. vscode实现 二、布局1. 盒子模型2. 布局标签< div >和< span >3. VScode实现 三、源代码和运行结果总结 前言 本篇文章是…...

Java | Leetcode Java题解之第283题移动零
题目: 题解: class Solution {public void moveZeroes(int[] nums) {int n nums.length, left 0, right 0;while (right < n) {if (nums[right] ! 0) {swap(nums, left, right);left;}right;}}public void swap(int[] nums, int left, int right)…...