news 2026/4/17 19:23:36

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/18 8:56:31

当代糊弄学巅峰:如何用AI写完你的年终总结,并让你老板热泪盈眶

面对空白的文档光标闪烁&#xff0c;你即将解锁职场终极技能&#xff1a;用AI把一年的摸鱼时光&#xff0c;编织成令老板动容的奋斗史诗。深夜十一点&#xff0c;办公室的灯光下&#xff0c;张伟对着电脑屏幕上只有“2025年度工作总结”几个字的文档发呆。过去一年的记忆如同碎…

作者头像 李华
网站建设 2026/4/18 5:30:58

告别高延迟!用TensorRT镜像优化你的LLM推理流程

告别高延迟&#xff01;用TensorRT镜像优化你的LLM推理流程 在大模型落地的浪潮中&#xff0c;一个看似不起眼却频频卡脖子的问题正困扰着无数工程师&#xff1a;为什么训练好的LLM一到生产环境就“卡成PPT”&#xff1f; 用户提问刚发出去&#xff0c;系统要等两秒才开始打字&…

作者头像 李华
网站建设 2026/4/18 11:31:06

详解TensorRT层融合技术:如何减少模型计算冗余

详解TensorRT层融合技术&#xff1a;如何减少模型计算冗余 在今天的AI系统中&#xff0c;一个训练得再精准的模型&#xff0c;如果推理延迟高、吞吐量低&#xff0c;也难以在真实业务场景中落地。比如&#xff0c;智能安防摄像头每秒要处理数十路视频流&#xff0c;推荐系统需要…

作者头像 李华
网站建设 2026/4/17 18:42:57

INT8精度校准全攻略:在TensorRT中实现无损压缩

INT8精度校准全攻略&#xff1a;在TensorRT中实现无损压缩 在自动驾驶的感知系统里&#xff0c;一个实时目标检测模型需要在30毫秒内完成推理&#xff1b;在智能音箱背后&#xff0c;语音识别模块必须以极低功耗持续监听唤醒词。这些场景背后都有一个共同挑战&#xff1a;如何…

作者头像 李华
网站建设 2026/4/18 8:56:41

使用TensorRT优化Text-to-SQL自然语言查询转换

使用TensorRT优化Text-to-SQL自然语言查询转换 在企业智能化转型的浪潮中&#xff0c;越来越多的业务系统开始尝试让用户“用说话的方式”访问数据库。比如&#xff0c;销售主管在移动端输入一句&#xff1a;“上个月华东区销售额最高的产品是什么&#xff1f;”系统便能自动生…

作者头像 李华
网站建设 2026/4/17 21:35:50

模型转换全流程:ONNX转TensorRT引擎避坑指南

模型转换全流程&#xff1a;ONNX转TensorRT引擎避坑指南 在AI模型从实验室走向产线的过程中&#xff0c;一个绕不开的挑战就是——为什么训练时表现完美的模型&#xff0c;一到线上推理就卡顿、延迟高、吞吐上不去&#xff1f; 答案往往不在算法本身&#xff0c;而在于部署环…

作者头像 李华