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

Vue.js 自定义指令

一、什么是自定义指令?

Vue 内置了v-modelv-showv-if等指令,自定义指令就是自己造一个v-xxx,用来对 DOM 元素进行底层操作。

适用场景:需要直接操作 DOM,且逻辑可复用的情况,如自动聚焦、权限控制、拖拽、懒加载等。

二、基本用法

注册指令

// 全局注册app.directive('focus',{mounted(el){el.focus();}});// 局部注册exportdefault{directives:{focus:{mounted(el){el.focus();}}}};

使用指令

<inputv-focus/>

三、指令钩子函数

Vue 3 钩子

app.directive('my-dir',{// 元素被插入 DOM 前created(el,binding,vnode){},// 元素插入 DOM 后(最常用)mounted(el,binding,vnode){},// 组件更新后updated(el,binding,vnode,prevVnode){},// 元素卸载前beforeUnmount(el,binding,vnode){},// 元素卸载后unmounted(el,binding,vnode){},});

Vue 2 钩子(名称不同)

Vue.directive('my-dir',{bind(el,binding,vnode){},// → 对应 Vue 3 的 mountedinserted(el,binding,vnode){},// → 对应 Vue 3 的 mountedupdate(el,binding,vnode){},// → 对应 Vue 3 的 updatedcomponentUpdated(el,binding){},// → 对应 Vue 3 的 updatedunbind(el,binding,vnode){},// → 对应 Vue 3 的 unmounted});

Vue 2 vs Vue 3 钩子对照

Vue 2Vue 3
bindmounted
insertedmounted
updateupdated
componentUpdatedupdated
unbindunmounted

四、钩子参数

mounted(el,binding,vnode){// el:指令绑定的 DOM 元素,可直接操作// binding:一个对象,包含以下属性}

binding 对象

<divv-my-dir:arg.modifier="value"/>
{value:...,// 指令的绑定值,如 v-my-dir="1+1" → 2oldValue:...,// 上一次的值(仅在 updated 中可用)arg:'arg',// 指令参数,如 v-my-dir:foo → 'foo'modifiers:{// 修饰符对象modifier:true// 如 v-my-dir.bold → { bold: true }},instance:...,// 组件实例dir:...,// 指令定义对象本身}

五、简写形式

如果只在mountedupdated时执行相同逻辑,可以用函数简写:

// 完整写法app.directive('color',{mounted(el,binding){el.style.color=binding.value;},updated(el,binding){el.style.color=binding.value;}});// 简写(mounted + updated 都执行)app.directive('color',(el,binding)=>{el.style.color=binding.value;});

六、实战示例

1. 自动聚焦 v-focus

app.directive('focus',{mounted(el){el.focus();}});
<inputv-focus/><!-- 页面加载后自动聚焦 -->

2. 权限控制 v-permission

app.directive('permission',{mounted(el,binding){constuserRoles=['user'];// 当前用户角色constrequiredRole=binding.value;if(!userRoles.includes(requiredRole)){el.parentNode?.removeChild(el);// 无权限则移除元素}}});
<buttonv-permission="'admin'">删除用户</button><!-- 普通用户看不到这个按钮 -->

3. 防抖 v-debounce

app.directive('debounce',{mounted(el,binding){lettimer=null;el.addEventListener('click',()=>{if(timer)clearTimeout(timer);timer=setTimeout(()=>{binding.value();},500);});}});
<buttonv-debounce="handleSubmit">提交</button>

4. 拖拽 v-draggable

app.directive('draggable',{mounted(el){el.style.position='absolute';el.style.cursor='move';letisDragging=false;letstartX,startY,initialLeft,initialTop;el.addEventListener('mousedown',(e)=>{isDragging=true;startX=e.clientX;startY=e.clientY;initialLeft=el.offsetLeft;initialTop=el.offsetTop;});document.addEventListener('mousemove',(e)=>{if(!isDragging)return;constdx=e.clientX-startX;constdy=e.clientY-startY;el.style.left=initialLeft+dx+'px';el.style.top=initialTop+dy+'px';});document.addEventListener('mouseup',()=>{isDragging=false;});}});
<divv-draggable>拖我</div>

5. 图片懒加载 v-lazy

app.directive('lazy',{mounted(el,binding){constobserver=newIntersectionObserver((entries)=>{entries.forEach(entry=>{if(entry.isIntersecting){el.src=binding.value;// 进入视口时加载图片observer.unobserve(el);// 停止观察}});});observer.observe(el);}});
<imgv-lazy="/images/photo.jpg"alt="photo"/>

6. 复制文本 v-copy

app.directive('copy',{mounted(el,binding){el.style.cursor='pointer';el.addEventListener('click',()=>{navigator.clipboard.writeText(binding.value).then(()=>{console.log('复制成功');});});}});
<spanv-copy="shareLink">点击复制链接</span>

七、动态指令参数

Vue 3 支持动态指令参数:

<!-- 动态决定设置哪个 CSS 属性 --><divv-color:[cssProp]="'red'"/><!-- 等价于 --><divv-color:color="'red'"/><!-- 当 cssProp = 'color' -->
app.directive('color',(el,binding)=>{el.style[binding.arg]=binding.value;// binding.arg = 'color' → el.style.color = 'red'});

八、总结

要点说明
什么时候用需要直接操作 DOM 且逻辑可复用
怎么注册app.directive()全局 /directives选项局部
最常用钩子mounted(元素插入后操作)
简写函数形式 =mounted+updated
核心参数el(DOM 元素)、binding.value(绑定值)
别忘了操作 DOM 后在unmounted中清理(移除事件监听等)
http://www.jsqmd.com/news/746213/

相关文章:

  • svg-sprite-loader服务器端渲染实践:SSR环境下的SVG精灵处理
  • 日志不输出、断点不命中、变量全为None——Python低代码插件调试困局全解析,深度穿透沙箱隔离层
  • 别再死记硬背了!用RabbitMQ Web管理界面5分钟搞懂Topic通配符(附实战截图)
  • 2026年4月口碑好的网带螺旋塔供应商推荐,斗式提升机/食品紫外线杀菌炉/网带烘干机/乙型网带,网带螺旋塔直销厂家有哪些 - 品牌推荐师
  • 终极dnSpy性能分析指南:快速找出代码生成瓶颈的10个技巧
  • 【仅限头部金融/政务系统内部流出】:Java多租户数据隔离最小可行配置矩阵(含Oracle/PostgreSQL/MySQL三端差异表)
  • Python跨端项目上线前必须完成的9项合规审计,少1项即遭App Store拒审
  • 5个必备星露谷物语mod:终极自动化与效率提升指南
  • Claude Code 源码下载后如何配置 Taotoken 实现稳定 API 调用
  • 平衡小车调参实录:我是如何用上位机示波器‘看’着调好串级PID的
  • 从U-Net到YOLOv8-seg:手把手教你理解图像分割的Predict流程(附代码逐行解析)
  • 【AI面试八股文 Vol.1.3:ReAct】ReAct 不是一种算法,是一种工程契约:从问题域到面试追问的完整映射
  • 7天掌握计算机基础:InterviewGuide 学习路线终极指南
  • 终极指南:如何在Mac上完美使用Xbox手柄玩游戏
  • 如何快速部署r77-rootkit:5步安装指南与实战演示
  • 如何快速构建多语言企业级应用:Egg.js国际化完整指南
  • Windows上运行iOS应用的终极指南:ipasim跨平台模拟器详解
  • FontForge终极指南:免费开源字体编辑器的完整入门教程
  • Anthropic和DeepMind在技术路径上有何不同?
  • Vue.js 路由
  • 别再只盯着OES了!干法刻蚀中,如何利用设备日志和RF匹配参数实现低成本终点检测?
  • 亲测有效!海康IVMS-4200 V2.8.2.2老版本下载与降级安装保姆级教程(解决Win10/Win Server兼容性)
  • C++ string全面解析:从入门到精通
  • 同济高数第七版第一章:函数与极限,我用Python画图帮你理解(附代码)
  • 如何用命令行工具3分钟搞定光猫配置?zteOnu让你的网络管理效率飙升
  • Backtrader机器学习交易策略终极指南:从特征工程到智能部署的完整教程
  • 领域专用AI助手开发:提示工程与安全防护实战
  • 2026文昌航天一站式服务领域哪一家机构提供的服务更加专业 - 热敏感科技蜂
  • Solon AI v.. 发布(智能体开发框架,支持 Java 到 Java)
  • SOGo API开发指南:构建企业级协作应用的终极指南