当前位置: 首页 > news >正文

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图书管理系统_普通用户+管理员菜单(源码+论文)【独一无二】

&#x1f449;博__主&#x1f448;&#xff1a;米码收割机 &#x1f449;技__能&#x1f448;&#xff1a;C/Python语言 &#x1f449;公众号&#x1f448;&#xff1a;测试开发自动化【获取源码商业合作】 &#x1f449;荣__誉&#x1f448;&#xff1a;阿里云博客专家博主、5…...

智能路面裂缝检测:基于YOLO和深度学习的全流程实现

引言 路面裂缝检测是维护道路质量和延长道路寿命的重要手段。传统的检测方法往往费时费力且易受人为因素影响。为了提高检测效率和准确性&#xff0c;本文介绍了一种基于深度学习的路面裂缝检测系统。该系统包括用户界面&#xff0c;利用YOLO&#xff08;You Only Look Once&a…...

C++ unordered_map

1. unordered系列关联式容器 在C98 中&#xff0c; STL 提供了底层为红黑树结构的一系列关联式容器&#xff0c;在查询时效率可达到 &#xff0c;即最差情况下需要比较红黑树的高度次&#xff0c;当树中的节点非常多时&#xff0c;查询效率也不理想。最好的查询是&#xff0c…...

PHP Switch 语句

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

electron 网页TodoList应用打包win桌面软件数据持久化

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

软件缺陷(Bug)、禅道

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

MySQL客户端命令一节将.sql文件导入MySQL

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

[论文笔记] DCA(Dual Chunk Attention)

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

构建查询洞察 UI

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

【北京迅为】《i.MX8MM嵌入式Linux开发指南》-第三篇 嵌入式Linux驱动开发篇-第五十九章 等待队列

i.MX8MM处理器采用了先进的14LPCFinFET工艺&#xff0c;提供更快的速度和更高的电源效率;四核Cortex-A53&#xff0c;单核Cortex-M4&#xff0c;多达五个内核 &#xff0c;主频高达1.8GHz&#xff0c;2G DDR4内存、8G EMMC存储。千兆工业级以太网、MIPI-DSI、USB HOST、WIFI/BT…...

35.【C语言】详解函数递归

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

【机器学习】智驭未来:机器学习如何重塑制造业的转型与升级

&#x1f4dd;个人主页&#x1f339;&#xff1a;Eternity._ &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; ❀目录 &#x1f50d;1. 引言&#x1f4d2;2. 机器学习重塑制造业生产流程&#x1f338;预测性维护&#xff1a;减少停机时间&#xff0c;提高设…...

Python爬虫(5) --爬取网页视频

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

【Unity】关于Luban的简单使用

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

企业公户验证API如何使用JAVA、Python、PHP语言进行应用

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

杰发科技Bootloader(2)—— 基于7840的Keil配置地址

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

cmd常用命令

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

PCIe 以太网芯片 RTL8125B 的 spec 和 Linux driver 分析备忘

1,下载 RTL8125B driver 下载页&#xff1a; https://www.realtek.com/Download/List?cate_id584 2,RTL8125B datasheet下载 下载页&#xff1a; https://file.elecfans.com/web2/M00/44/D8/poYBAGKHVriAHnfWADAT6T6hjVk715.pdf3, 编译driver 解压&#xff1a; $ tar xj…...

Python tkinter Menu菜单组件详解

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

IDEA运行Tomcat出现乱码问题解决汇总

最近正值期末周&#xff0c;有很多同学在写期末Java web作业时&#xff0c;运行tomcat出现乱码问题&#xff0c;经过多次解决与研究&#xff0c;我做了如下整理&#xff1a; 原因&#xff1a; IDEA本身编码与tomcat的编码与Windows编码不同导致&#xff0c;Windows 系统控制台…...

Android Wi-Fi 连接失败日志分析

1. Android wifi 关键日志总结 (1) Wi-Fi 断开 (CTRL-EVENT-DISCONNECTED reason3) 日志相关部分&#xff1a; 06-05 10:48:40.987 943 943 I wpa_supplicant: wlan0: CTRL-EVENT-DISCONNECTED bssid44:9b:c1:57:a8:90 reason3 locally_generated1解析&#xff1a; CTR…...

Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以?

Golang 面试经典题&#xff1a;map 的 key 可以是什么类型&#xff1f;哪些不可以&#xff1f; 在 Golang 的面试中&#xff0c;map 类型的使用是一个常见的考点&#xff0c;其中对 key 类型的合法性 是一道常被提及的基础却很容易被忽视的问题。本文将带你深入理解 Golang 中…...

Spring Boot 实现流式响应(兼容 2.7.x)

在实际开发中&#xff0c;我们可能会遇到一些流式数据处理的场景&#xff0c;比如接收来自上游接口的 Server-Sent Events&#xff08;SSE&#xff09; 或 流式 JSON 内容&#xff0c;并将其原样中转给前端页面或客户端。这种情况下&#xff0c;传统的 RestTemplate 缓存机制会…...

使用分级同态加密防御梯度泄漏

抽象 联邦学习 &#xff08;FL&#xff09; 支持跨分布式客户端进行协作模型训练&#xff0c;而无需共享原始数据&#xff0c;这使其成为在互联和自动驾驶汽车 &#xff08;CAV&#xff09; 等领域保护隐私的机器学习的一种很有前途的方法。然而&#xff0c;最近的研究表明&…...

YSYX学习记录(八)

C语言&#xff0c;练习0&#xff1a; 先创建一个文件夹&#xff0c;我用的是物理机&#xff1a; 安装build-essential 练习1&#xff1a; 我注释掉了 #include <stdio.h> 出现下面错误 在你的文本编辑器中打开ex1文件&#xff0c;随机修改或删除一部分&#xff0c;之后…...

测试markdown--肇兴

day1&#xff1a; 1、去程&#xff1a;7:04 --11:32高铁 高铁右转上售票大厅2楼&#xff0c;穿过候车厅下一楼&#xff0c;上大巴车 &#xffe5;10/人 **2、到达&#xff1a;**12点多到达寨子&#xff0c;买门票&#xff0c;美团/抖音&#xff1a;&#xffe5;78人 3、中饭&a…...

DIY|Mac 搭建 ESP-IDF 开发环境及编译小智 AI

前一阵子在百度 AI 开发者大会上&#xff0c;看到基于小智 AI DIY 玩具的演示&#xff0c;感觉有点意思&#xff0c;想着自己也来试试。 如果只是想烧录现成的固件&#xff0c;乐鑫官方除了提供了 Windows 版本的 Flash 下载工具 之外&#xff0c;还提供了基于网页版的 ESP LA…...

NLP学习路线图(二十三):长短期记忆网络(LSTM)

在自然语言处理(NLP)领域,我们时刻面临着处理序列数据的核心挑战。无论是理解句子的结构、分析文本的情感,还是实现语言的翻译,都需要模型能够捕捉词语之间依时序产生的复杂依赖关系。传统的神经网络结构在处理这种序列依赖时显得力不从心,而循环神经网络(RNN) 曾被视为…...

Caliper 配置文件解析:config.yaml

Caliper 是一个区块链性能基准测试工具,用于评估不同区块链平台的性能。下面我将详细解释你提供的 fisco-bcos.json 文件结构,并说明它与 config.yaml 文件的关系。 fisco-bcos.json 文件解析 这个文件是针对 FISCO-BCOS 区块链网络的 Caliper 配置文件,主要包含以下几个部…...