news 2026/9/1 22:00:57

vue2 和 vue3自定义指令有什么区别,都是怎么实现和使用一个指令

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
vue2 和 vue3自定义指令有什么区别,都是怎么实现和使用一个指令

vue2 和 vue3自定义指令有什么区别,都是怎么实现和使用一个指令

Vue2 和 Vue3自定义指令(Custom Directive)整体思想一样:

直接操作 DOM 的一种扩展机制,通常用于权限控制、焦点、拖拽、懒加载等。

但 API 设计、生命周期、实现方式有明显变化。

4个层面:

1️⃣ Vue2 vs Vue3 指令生命周期区别
2️⃣ Vue2 按钮权限指令实现
3️⃣ Vue3 按钮权限指令实现
4️⃣ Vue3 指令底层设计变化

一、Vue2 vs Vue3 指令生命周期区别

Vue2 指令钩子

Vue2 指令有 5个生命周期

钩子说明
bind指令第一次绑定到元素
inserted元素插入 DOM
updateVNode 更新
componentUpdated组件更新完成
unbind解绑

示例

Vue.directive('focus',{bind(el){},inserted(el){},update(el){},componentUpdated(el){},unbind(el){}})

Vue3 指令生命周期

Vue3 完全重写了指令生命周期,名字和组件生命周期保持一致。

Vue2Vue3
bindbeforeMount
insertedmounted
updateupdated
componentUpdatedupdated
unbindunmounted

示例

app.directive('focus',{beforeMount(el){},mounted(el){},updated(el){},unmounted(el){}})

二、Vue2 按钮权限指令实现

企业中最常见的自定义指令就是:

按钮权限控制

v-permission

例如

<buttonv-permission="'user:add'">新增</button>

如果没有权限:按钮直接删除

Vue2 指令实现

  1. 定义指令
importstorefrom'@/store'Vue.directive('permission',{inserted(el,binding){const{value}=bindingconstpermissions=store.state.user.permissionsif(value&&valueinstanceofArray){consthasPermission=permissions.some(p=>value.includes(p))if(!hasPermission){el.parentNode.removeChild(el)}}else{thrownewError('权限指令需要数组')}}})
  1. 使用指令
<buttonv-permission="['user:add']">新增用户</button>

binding 参数结构

Vue2:

binding={name:'permission',value:['user:add'],oldValue:undefined,expression:"['user:add']",arg:undefined,modifiers:{}}

三、Vue3 按钮权限指令实现

Vue3 写法更简洁。

  1. 创建指令

src/directives/permission.ts

importtype{Directive}from'vue'import{useUserStore}from'@/store/user'exportconstpermission:Directive={mounted(el,binding){const{value}=bindingconstuserStore=useUserStore()constpermissions=userStore.permissionsconsthasPermission=permissions.some(p=>value.includes(p))if(!hasPermission){el.parentNode?.removeChild(el)}}}
  1. 注册指令

main.ts

import{createApp}from'vue'import{permission}from'@/directives/permission'constapp=createApp(App)app.directive('permission',permission)app.mount('#app')
  1. 使用指令
<buttonv-permission="['user:add']">新增用户</button>

四、Vue3 指令底层设计变化

Vue3 指令其实是 VNode patch 阶段执行。

关键源码在:

runtime-core/directives.ts

核心函数:

invokeDirectiveHook

简化源码:

exportfunctioninvokeDirectiveHook(vnode,prevVNode,instance,name){constbindings=vnode.dirsfor(leti=0;i<bindings.length;i++){constbinding=bindings[i]consthook=binding.dir[name]if(hook){hook(vnode.el,binding,vnode,prevVNode)}}}

执行流程:

template ↓ 编译成 render ↓ VNode 上挂 dirs ↓ patch 阶段 ↓ invokeDirectiveHook ↓ 执行 mounted / updated

VNode结构:

{type:'button',props:{},dirs:[{dir:permission,value:['user:add']}]}

五、Vue2 vs Vue3 指令实现差异

区别Vue2Vue3
注册Vue.directiveapp.directive
生命周期bind inserted updatebeforeMount mounted updated
调用时机patchpatch
binding 参数复杂更简单
类型支持TS Directive 类型
底层实现directive.jsruntime-core/directives.ts

六、 Vue3 指令系统真正的运行路径

源码执行链路

template ↓ 编译 render ↓ withDirectives() ↓ VNode.dirs ↓ patch() ↓ invokeDirectiveHook() ↓ 执行 mounted / updated / unmounted

七、模板里的指令是怎么变成 VNode 的

模板

<buttonv-permission="['user:add']">新增</button>

编译后的 render 函数(简化版)

import{withDirectives,createVNode}from"vue"returnwithDirectives(createVNode("button",null,"新增"),[[permission,['user:add']]])

关键函数:

withDirectives()

函数的作用是:把指令挂到 VNode 上

八、withDirectives 源码

源码位置:

packages/runtime-core/src/directives.ts

核心代码(简化)

exportfunctionwithDirectives(vnode,directives){constbindings=vnode.dirs||(vnode.dirs=[])for(leti=0;i<directives.length;i++){let[dir,value,arg,modifiers]=directives[i]bindings.push({dir,value,arg,modifiers})}returnvnode}

执行完之后:

VNode 结构会变成:

{type:"button",props:null,children:"新增",dirs:[{dir:permission,value:['user:add'],arg:undefined,modifiers:{}}]}

重点:VNode.dirs这里存放所有指令

九、patch 阶段如何执行指令

Vue3 DOM 渲染核心:renderer.ts

当元素创建时:mountElement()

核心流程:mountElement(vnode, container)

简化代码:

constmountElement=(vnode,container)=>{constel=vnode.el=document.createElement(vnode.type)// propspatchProps(el)// childrenmountChildren()// 指令 mountedif(vnode.dirs){invokeDirectiveHook(vnode,null,parentComponent,'mounted')}}

所以:mounted是在DOM 创建完成之后执行

十、invokeDirectiveHook(核心函数)

源码:

runtime-core/directives.ts

核心代码:

exportfunctioninvokeDirectiveHook(vnode,prevVNode,instance,name){constbindings=vnode.dirsfor(leti=0;i<bindings.length;i++){constbinding=bindings[i]consthook=binding.dir[name]if(hook){hook(vnode.el,binding,vnode,prevVNode)}}}

执行逻辑:

遍历 vnode.dirs ↓ 找到对应生命周期 ↓ 执行 mounted / updated

调用指令:

permission.mounted(el,binding)

十一、binding 参数真正结构

当 VNode 更新:patchElement()

源码:

if(dirs){invokeDirectiveHook(n2,n1,parentComponent,'updated')}

执行顺序:

patch props patch children ↓ directive updated

所以:updated 一定在 DOM 更新后执行

十二、指令 unmounted 执行时机

组件卸载:unmount()

源码:

if(vnode.dirs){invokeDirectiveHook(vnode,null,instance,'unmounted')}

十三、Vue2 指令底层 vs Vue3 指令底层

Vue2 指令是在:patch.js执行updateDirectives()

源码:

functionupdateDirectives(oldVnode,vnode){constdirs=normalizeDirectives()for(keyindirs){callHook(dir,'bind')}}

逻辑非常复杂

Vue3重写原因:

1️⃣ 生命周期混乱
2️⃣ diff逻辑复杂
3️⃣ 指令和组件生命周期不一致

Vue3改进:

统一生命周期 统一调用入口 VNode直接挂 dirs

后话:

为什么 Vue3 要有 withDirectives

Vue3 是 函数式 VNode 创建:

h('button')

没有 template 的情况下:

h('button', {}, '新增')

只能:

withDirectives()

withDirectives(h('button'),[[permission,['user:add']]])

所以:withDirectives 是 render 层 API

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

2026数字人制作软件十大免费试用榜:先体验后付费的平台推荐清单

一、引言在数字人应用逐步渗透各行业的当下&#xff0c;不少个人创作者、中小企业都想借助数字人制作软件实现内容生产降本增效&#xff0c;却普遍存在付费前怕踩坑、担心软件功能与需求不匹配的顾虑。大家最关心的问题集中在&#xff1a;免费试用的数字人制作软件是否能开放核…

作者头像 李华
网站建设 2026/7/14 17:27:01

开源项目吐槽大会

开源项目吐槽大会&#xff1a;技术文章大纲背景与目的开源项目的快速发展与社区文化吐槽大会的意义&#xff1a;促进交流、改进项目、增强社区凝聚力技术视角下的吐槽&#xff1a;从代码质量到维护流程常见的开源项目槽点文档不完善或过时代码结构混乱或缺乏注释响应速度慢或维…

作者头像 李华
网站建设 2026/7/14 17:27:15

2026最值得买的全方位旗舰电视,雷鸟鹤7 Pro 26款正式亮相

从行业视角观察&#xff0c;电视市场的竞争逻辑正在悄然生变&#xff1a;一方面&#xff0c;消费者对家庭影院的想象被大屏重新点燃&#xff0c;85寸以上巨幕电视正从“小众选择”走向“主流标配”&#xff1b;另一方面&#xff0c;单纯堆参数的“数据游戏”已难以为继&#xf…

作者头像 李华
网站建设 2026/7/14 17:27:13

蓝桥杯刷题总结:寻找字典序最大的回文子序列

P12344 [蓝桥杯 2025 省 B/Python B 第二场] 破解信息 - 洛谷 分析 乍看题目&#xff0c;既要不连续子序列&#xff0c;又要回文串&#xff0c;又要字典序最大 我们的思路可能会被误导&#xff0c;可能会先找所有是回文串的子序列&#xff0c;再把所有符合要求的子序列进行字…

作者头像 李华
网站建设 2026/7/14 17:27:14

【游戏开发】全新3D 游戏开发 AI 提示词系列第二弹之 RPG 与冒险篇

摘要&#xff1a;本文是 3D 游戏开发 AI 提示词系列第二弹的开篇&#xff0c;精选前 10 条 RPG 与冒险类开发提示词。涵盖 Unity、Unreal、Three.js 等引擎&#xff0c;每条包含 9 项功能要求。适合中高级开发者构建复杂游戏系统。关键词&#xff1a;游戏开发&#xff1b;AI 辅…

作者头像 李华