封装和使用自定义指令
在 Vue 中封装自定义指令是增强 DOM 操作能力的有效方式,下面通过几个典型场景展示如何封装和使用自定义指令。
基础自定义指令封装
示例 1:自动聚焦指令
// directives/focus.jsexport const focus = { mounted(el) { el.focus() // 元素挂载后自动聚焦 }}// 在组件中使用 import { focus } from \'@/directives/focus\'export default { directives: { focus }}
示例 2:权限控制指令
// directives/permission.jsexport const permission = { mounted(el, binding) { const { value } = binding const userRoles = [\'admin\'] // 假设从 store 获取用户角色 if (!userRoles.includes(value)) { el.parentNode && el.parentNode.removeChild(el) // 无权限则移除元素 } }}// 在组件中使用
带参数和修饰符的指令
示例 3:防抖指令
// directives/debounce.jsexport const debounce = { mounted(el, binding) { const { value, arg = \'click\', modifiers } = binding const delay = modifiers.large ? 1000 : 300 let timer = null el.addEventListener(arg, () => { clearTimeout(timer) timer = setTimeout(() => value(), delay) }) }}// 在组件中使用
全局注册自定义指令
示例 4:在入口文件中全局注册
// main.jsimport { createApp } from \'vue\'import App from \'./App.vue\'// 批量导入指令import * as directives from \'./directives\'const app = createApp(App)// 全局注册所有指令Object.keys(directives).forEach(key => { app.directive(key, directives[key])})app.mount(\'#app\')
高级用法:动态指令参数
示例 5:图片懒加载指令
// directives/lazy.jsexport const lazy = { mounted(el, binding) { const observer = new IntersectionObserver((entries) => { entries.forEach(entry => { if (entry.isIntersecting) { el.src = binding.value // 进入视口时设置真实图片地址 observer.unobserve(el) // 加载后停止观察 } }) }) observer.observe(el) // 开始观察元素 }}// 在组件中使用 ![懒加载图片]()
生命周期钩子
自定义指令有以下生命周期钩子:
beforeMount
:指令第一次绑定到元素且在挂载父组件之前调用mounted
:元素已插入父 DOM 后调用beforeUpdate
:组件更新前调用updated
:组件更新后调用beforeUnmount
:元素卸载前调用unmounted
:元素卸载后调用
指令参数解构
在钩子函数中可以解构参数:
mounted(el, { value, arg, modifiers }) { // value: v-my-directive=\"xxx\" 中的 xxx // arg: v-my-directive:xxx 中的 xxx // modifiers: v-my-directive.xxx 中的 xxx}
注意事项
- DOM 操作:自定义指令主要用于直接操作 DOM,避免复杂业务逻辑
- 性能考量:频繁触发的指令(如滚动监听)需结合防抖 / 节流
- 兼容性:使用原生 DOM API 时需考虑浏览器兼容性
- 全局注册:常用指令建议全局注册,避免重复导入
通过合理封装自定义指令,可以大幅提升代码复用性和开发效率。