news 2026/4/23 21:06:40

Vue.directive:自定义指令及传参

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Vue.directive:自定义指令及传参

Vue官方提供很多指令,比如:v-model,v-show,v-if,v-on等,他们都以v-开头。当这些指令不能满足实际开发需求时,我们可以自定义指令,包括全局自定义指令和局部自定义指令。聚焦于底层DOM操作,用于修改元素的样式、操作DOM、处理事件等。

一、指令封装

1、 v-dialogDragWidth: 拖拽 el-dialog 弹窗宽度拖大、 拖小

import Vue from 'vue' // v-dialogDragWidth: 弹窗宽度拖大 拖小 Vue.directive('dialogDragWidth', { bind(el, binding, vnode, oldVnode) { const dragDom = binding.value.$el.querySelector('.el-dialog') el.onmousedown = (e) => { // 鼠标按下,计算当前元素距离可视区的距离 const disX = e.clientX - el.offsetLeft document.onmousemove = function(e) { e.preventDefault() // 移动时禁用默认事件 // 通过事件委托,计算移动的距离 const l = e.clientX - disX dragDom.style.width = `${l}px` } document.onmouseup = function(e) { document.onmousemove = null document.onmouseup = null } } } })

2、v-lazy :图片懒加载,监听scroll事件并计算元素位置

import Vue from 'vue' // v-lazy: 图片懒加载 Vue.directive('lazy', { inserted(el, binding) { const observer = new IntersectionObserver((entries) => { if (entries[0].isIntersecting) { el.src = binding.value observer.unobserve(el) } }) observer.observe(el) } })
二、指令使用

1、在 utils 中新建 directives.js 文件
2、main.js中导入:import ‘./utils/directives.js’
3、使用指令的地方加入 dialogDragWidth 、v-lazy

<el-dialog :visible.sync="dialogVisible" v-dialogDragWidth> // ...... </el-dialog> <img v-lazy="detail.imageUrl">
三、指令扩展
1. 指令钩子函数
一个指令定义对象可以提供如下几个钩子函数 (均为可选):

bind:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。

inserted:被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。

update:所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变,也可能没有。但是你可以通过比较更新前后的值来忽略不必要的模板更新。

componentUpdated:指令所在组件的 VNode 及其子 VNode 全部更新后调用。

unbind:只调用一次,指令与元素解绑时调用。

每个钩子函数有以下参数:
  1. el:指令所绑定的元素,可以用来直接操作 DOM。
  2. binding:一个对象,包含以下 property:

name:指令名,不包括 v- 前缀。
value:指令的绑定值,例如:v-my-directive="1 + 1" 中,绑定值为 2。
oldValue:指令绑定的前一个值,仅在 update 和 componentUpdated 钩子中可用。无论值是否改变都可用。
expression:字符串形式的指令表达式。例如 v-my-directive="1 + 1" 中,表达式为 "1 + 1"。
arg:传给指令的参数,可选。例如 v-my-directive:foo 中,参数为 "foo"。
modifiers:一个包含修饰符的对象。例如:v-my-directive.foo.bar 中,修饰符对象为 { foo: true, bar: true }。
vnode:Vue 编译生成的虚拟节点。
oldVnode:上一个虚拟节点,仅在 update 和 componentUpdated 钩子中可用。

代码实现:
import Vue from 'vue' Vue.directive('tooltip',{ bind(el, binding) { // 当指令绑定到 HTML 元素上时触发.**只调用一次,适合进行一次性初始化** console.log('bind triggerd') el.style.position = 'relative' const tooltip = document.createElement('div') tooltip.className = 'tooltip' tooltip.textContent = binding.value el._tooltip = tooltip document.body.appendChild(tooltip) }, inserted(el, binding) { // 当绑定了指令的这个HTML元素插入到父元素上时触发(在这里父元素是 `div#app`)**.但不保证,父元素已经插入了 DOM 文档.**。若父元素初始为 display:none,获取的尺寸可能不准确,需结合MutationObserver监听显示状态变化。 console.log('inserted triggerd') const rect = el.getBoundingClientRect() el._tooltip.style.cssText = ` position: absolute; left: ${rect.left + rect.width/2}px; top: ${rect.top - 30}px; ` }, updated(el, binding) { // 所在组件的`VNode`更新时调用. 但会忽略首次绑定 console.log('updated triggerd') if (binding.value !== binding.oldValue) { el._tooltip.textContent = binding.value } }, componentUpdated(el, binding) { // 指令所在组件的 VNode 及其子 VNode 全部更新后调用。 console.log('componentUpdated triggerd') // 适合在子组件更新后重新计算位置 const rect = el.getBoundingClientRect() // 更新tooltip位置... }, unbind(el, binding) { // 只调用一次,指令与元素解绑时调用. 必须进行资源释放,若忘记移除事件监听器或全局对象,会导致内存泄漏 console.log('unbind triggerd') if (el._tooltip) { document.body.removeChild(el._tooltip) delete el._tooltip } } })
四、指令参数传参
1、传递静态参数

在自定义指令中传递静态参数,静态参数是指在指令绑定时已知的参数值。在HTML标签上使用指令时,使用冒号(:)来传递静态参数。例如,自定义指令叫做”v-dialogDragWidth”,我们可以通过这样的方式传递一个静态参数:

<div v-dialogDragWidth:arg="value"></div>

给 v-dialogDragWidth 指令传递了一个名为”arg”的静态参数,它的值为”value”。

我们可以在自定义指令的定义中通过”bind”钩子函数获取传入的参数,并在绑定元素上进行相应的操作:

Vue.directive('dialogDragWidth', {
bind: function(el, binding) {
console.log(binding.arg); // 输出:arg
console.log(binding.value); // 输出:value
// 在这里可以对绑定元素进行操作
}
});

2、传递动态参数

动态参数是指在指令绑定时不确定的参数值,根据不同的情况动态改变。在Vue中,我们可以使用方括号([])来传递动态参数:

<div v-dialogDragWidth:[arg]="value"></div>

或者

<div v-dialogDragWidth:[arg1,arg2,arg3]="value"></div>

我们给” v-dialogDragWidth ”指令传递了一个动态参数,它的值为”value”。在Vue实例中我们可以在数据中定义”arg”的值,并在渲染的时候动态改变它。例如:

data: {
arg: 'dynamicArg'
}

当数据中的”arg”发生变化时,指令中的动态参数也会相应地改变。在自定义指令的定义中,我们可以通过表达式来获取动态参数的值。

Vue.directive('dialogDragWidth', {
bind: function(el, binding) {
console.log(binding.arg); // 输出:dynamicArg
console.log(binding.value); // 输出:value
// 在这里可以对绑定元素进行操作
}
});

3、传参场景使用

通过对象形式动态传递参数,实现更灵活的权限控制:

// 使用方式:

<el-button v-permission:{"您没有删除权限"}="'delete'">删除</el-button>

// 数据处理:

Vue.directive('permission', {
bind(el, binding) {
const { value, arg } = binding // value:权限字符串,arg:错误提示
if (!checkPermission(value)) {
el.style.display = 'none'
el._permissionDenied = arg || '无权限访问'
}
}
})

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/23 7:49:26

稀疏化支持进展:TensorRT如何利用结构化剪枝

稀疏化支持进展&#xff1a;TensorRT如何利用结构化剪枝 在AI模型日益庞大的今天&#xff0c;一个典型的视觉或语言模型动辄拥有数十亿参数。这些模型虽然精度高&#xff0c;但在边缘设备上运行时却常常“水土不服”——推理延迟高、功耗大、吞吐量低。尤其是在自动驾驶、实时推…

作者头像 李华
网站建设 2026/4/23 9:20:25

CI/CD流水线集成:自动化模型优化与发布

CI/CD流水线集成&#xff1a;自动化模型优化与发布 在AI系统从实验室走向生产环境的过程中&#xff0c;一个常被低估却至关重要的挑战浮现出来&#xff1a;如何让训练好的深度学习模型&#xff0c;在真实业务场景中跑得又快又稳&#xff1f;尤其是在视频分析、实时推荐或自动驾…

作者头像 李华
网站建设 2026/4/23 9:17:07

django基于Spark的温布尔登特色赛赛事数据分析可视化平台设计与实现

背景分析 温布尔登网球锦标赛作为历史最悠久的大满贯赛事&#xff0c;其数据蕴含运动员表现、比赛趋势及商业价值等关键信息。传统数据分析工具在处理海量赛事数据时面临效率低、实时性差等问题。 技术整合意义 Spark分布式计算框架与Django的结合可解决以下问题&#xff1a…

作者头像 李华
网站建设 2026/4/23 9:20:03

自动内核调优揭秘:TensorRT如何匹配不同GPU架构

自动内核调优揭秘&#xff1a;TensorRT如何匹配不同GPU架构 在现代AI系统部署中&#xff0c;一个训练好的模型从实验室走向生产环境&#xff0c;往往面临巨大的性能落差。同样的ResNet-50模型&#xff0c;在PyTorch中推理一张图像可能需要20毫秒&#xff0c;而通过TensorRT优化…

作者头像 李华
网站建设 2026/4/23 9:20:17

为什么说TensorRT是大模型商业化落地的关键一环?

为什么说TensorRT是大模型商业化落地的关键一环&#xff1f; 在AI从“能用”迈向“好用”的今天&#xff0c;一个残酷的现实正摆在开发者面前&#xff1a;哪怕模型在实验室里表现惊艳&#xff0c;如果推理慢、成本高、吞吐低&#xff0c;它依然无法走进真实世界。尤其是在大模型…

作者头像 李华