news 2026/9/30 16:13:14

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/9/27 20:33:41

计费系统对接:按Token消耗统计TensorRT调用量

计费系统对接&#xff1a;按Token消耗统计TensorRT调用量 在AI服务逐渐走向商业化、产品化的今天&#xff0c;企业不再满足于“模型能跑通”这一基本要求&#xff0c;而是越来越关注——用户到底用了多少资源&#xff1f;该收多少钱&#xff1f; 尤其是大模型推理场景中&…

作者头像 李华
网站建设 2026/9/27 6:08:02

负载均衡配置:应对高并发下的TensorRT服务压力

负载均衡配置&#xff1a;应对高并发下的TensorRT服务压力 在当今AI驱动的生产系统中&#xff0c;用户对实时性的要求越来越高。想象一下&#xff1a;一个电商平台正在经历“双11”流量洪峰&#xff0c;成千上万的用户同时浏览商品列表&#xff0c;后台需要为每个人实时生成个性…

作者头像 李华
网站建设 2026/9/26 22:13:54

安卓平台集成TensorRT:打造本地化AI应用

安卓平台集成TensorRT&#xff1a;打造本地化AI应用 在智能设备越来越“懂你”的今天&#xff0c;从拍照时自动识别人脸、手势控制音乐播放&#xff0c;到车载系统实时监测驾驶员状态——这些看似轻巧的功能背后&#xff0c;是AI模型在终端侧默默运行的结果。用户不再满足于“能…

作者头像 李华
网站建设 2026/9/30 0:52:52

12.Python3函数基础:定义、调用与参数传递规则

1.Python3函数&#xff1a;让代码“打包复用” 你是否发现自己在代码中反复写着一模一样的片段&#xff1f;就像每次做饭都要从头切菜洗菜一样&#xff0c;函数就是帮你把这些重复操作打包成固定流程的好帮手。 什么是函数&#xff1f; 想象函数就像一个厨房小家电——你放入食…

作者头像 李华
网站建设 2026/9/29 6:53:39

学长亲荐10个AI论文工具,自考毕业论文轻松搞定!

学长亲荐10个AI论文工具&#xff0c;自考毕业论文轻松搞定&#xff01; AI 工具如何助力论文写作&#xff1f; 在自考毕业论文的准备过程中&#xff0c;许多学生都会面临一个共同的难题&#xff1a;如何高效、高质量地完成一篇符合要求的论文。随着 AI 技术的发展&#xff0c;越…

作者头像 李华
网站建设 2026/9/27 8:48:59

2026 年工作计划汇报 PPT:多种 AI 方案对比评估

告别低效&#xff01;轻竹办公让 2026 年工作计划汇报 PPT 高效出彩 每到年末年初&#xff0c;职场人最头疼的事莫过于制作工作计划汇报 PPT。为了一份高质量的 PPT&#xff0c;熬夜加班改报告成了常态。好不容易有了思路&#xff0c;却在搭建框架时犯了难&#xff0c;内容东拼…

作者头像 李华