自定义指令的基本语法
Vue.js 的自定义指令可以通过 Vue.directive 函数进行注册。该函数接受两个参数:指令名称和一个对象。对象包含指令的定义,其属性名对应着钩子函数,可以按照需要进行实现。
下面是一个示例代码:
Vue.directive('my-directive', {
bind: function (el, binding) {
// 绑定时的逻辑
},
inserted: function (el, binding) {
// 插入到 DOM 中后的逻辑
},
update: function (el, binding) {
// 组件更新时的逻辑
},
unbind: function (el, binding) {
// 取消绑定时的逻辑
}
})
上述代码中,我们使用 Vue.directive 函数来注册一个名为 my-directive 的指令,并传递了一个包含钩子函数的对象作为第二个参数。这些钩子函数将在指令生命周期的不同阶段被调用。
钩子函数
自定义指令的每个钩子函数都有其特定的用途:
bind:只调用一次,在指令第一次绑定到元素时调用。在这里可以进行一些初始化设置。inserted:当被绑定的元素插入到 DOM 中时调用。update:当组件更新时被调用,但是可能会被频繁触发,因此要注意性能问题。unbind:只调用一次,在指令与元素解绑时调用。
下面是一个示例代码,其中我们将在 my-directive 指令的 bind 钩子函数中为元素设置样式:
Vue.directive('my-directive', {
bind: function (el, binding) {
el.style.backgroundColor = binding.value
}
})
上述代码中,我们获取了指令的绑定值,并将其用作元素的背景色。
自定义指令的参数
除了钩子函数外,你还可以向自定义指令传递参数。指令参数可以通过指令名称后跟冒号和参数名的方式传递,例如 v-my-directive:param1="value"。
在自定义指令中,参数可以通过 binding.arg 进行访问,例如:
Vue.directive('my-directive', {
bind: function (el, binding) {
console.log(binding.arg) // 输出 param1
}
})
自定义指令的修饰符
除了参数外,Vue.js 的自定义指令还支持修饰符。修饰符是以点号 . 开头的特殊后缀,用于调整指令行为。例如,v-my-directive.foo 将添加一个名为 foo 的修饰符。
在自定义指令中,修饰符可以通过 binding.modifiers 进行访问,例如:
Vue.directive('my-directive', {
bind: function (el, binding) {
if (binding.modifiers.foo) {
// 在这里处理 foo 修饰符
}
}
})
项目中常用的自定义指令
1. 只允许输入数字的指令
Vue.directive('number-only', {
bind: function (el) {
el.addEventListener('input', function () {
this.value = this.value.replace(/[^\d]/g, '') // 只保留数字
})
}
})
该指令绑定到输入框上,只允许用户输入数字,其他字符将被自动删除。
2. 自动聚焦的指令
Vue.directive('autofocus', {
inserted: function (el) {
el.focus()
}
})
该指令绑定到输入框上,页面加载后会自动聚焦到该输入框。
3. 滚动时固定表头的指令
Vue.directive('fixed-header', {
inserted: function (el, binding) {
const tableElem = el.querySelector('.table')
const headerElem = el.querySelector('.header')
const wrapperElem = el.querySelector('.wrapper')
wrapperElem.style.overflowY = 'scroll'
wrapperElem.style.maxHeight = binding.value + 'px'
tableElem.style.width = '100%'
headerElem.style.position = 'sticky'
headerElem.style.top = 0
headerElem.style.zIndex = 1
}
})
该指令绑定到表格包裹元素上,在滚动时固定表头。其中,binding.value 表示表格内容的最大高度。
4. 点击元素外部关闭弹框的指令
Vue.directive('click-outside', {
bind: function (el, binding) {
const handler = function (e) {
if (!el.contains(e.target)) { // 判断点击位置是否在绑定元素内部
binding.value()
}
}
el.__vueClickOutside__ = handler
document.addEventListener('click', handler)
},
unbind: function (el) {
document.removeEventListener('click', el.__vueClickOutside__)
delete el.__vueClickOutside__
}
})
该指令绑定到需要关闭的弹框元素上,当用户点击元素外部时,会触发 binding.value 中的回调函数来关闭弹框。
5. 点击回车触发事件的指令
Vue.directive('enter', {
bind: function (el, binding) {
el.addEventListener('keyup', function (e) {
if (e.keyCode === 13) {
binding.value()
}
})
}
})
该指令绑定到输入框上,当用户按下回车键时,会触发 binding.value 中的回调函数来执行相应的操作。
6. 图片懒加载的指令
Vue.directive('lazyload', {
inserted: function (el, binding) {
const img = new Image()
img.src = binding.value // 绑定值为图片真实地址
img.onload = function () {
el.setAttribute('src', img.src)
}
}
})
该指令绑定到需要懒加载的图片元素上,当图片元素进入可视区域时,会将 binding.value 中的图片地址设置为 el 元素的 src 属性,从而实现图片懒加载。需要注意的是,该指令只适用于静态图片。对于动态生成的图片,可以使用第三方库,如 vue-lazyload。
7. 控制元素显示/隐藏的指令
Vue.directive('show', {
bind: function (el, binding) {
el.style.display = binding.value ? 'block' : 'none'
},
update: function (el, binding) {
el.style.display = binding.value ? 'block' : 'none'
}
})
该指令绑定到需要控制显示/隐藏的元素上,当 binding.value 为真时,元素会显示;否则,元素会隐藏。特别地,该指令在 update 钩子函数中也进行了处理,以便于在动态修改绑定值时可以实时更新元素的显示状态。
8. 禁用右键菜单的指令
Vue.directive('disable-right-click', {
bind: function (el) {
el.addEventListener('contextmenu', function (e) {
e.preventDefault()
})
}
})
该指令绑定到需要禁用右键菜单的元素上,当用户右击该元素时,会阻止浏览器默认的右键菜单弹出事件,从而实现禁用右键菜单的效果。