Vue 中自定义指令如何编写?有哪些常用场景?
自定义指令
// 全局注册
const app = createApp(App)
app.directive('focus', {
mounted(el) {
el.focus()
}
})
// 局部注册
<script setup>
const vFocus = {
mounted: (el) => el.focus()
}
</script>
<!-- 使用 -->
<input v-focus />指令钩子
app.directive('my-directive', {
// 元素挂载前
created(el, binding, vnode) {},
// 元素挂载前(CSS 已确定)
beforeMount(el, binding) {},
// 挂载后
mounted(el, binding) {},
// 更新前
beforeUpdate(el, binding) {},
// 更新后
updated(el, binding) {},
// 卸载前
beforeUnmount(el, binding) {},
// 卸载后
unmounted(el, binding) {}
})binding 对象
{
value: '传递的值', // v-my="value"
oldValue: '旧值', // 更新时的旧值
arg: 'foo', // v-my:foo
modifiers: { lazy: true }, // v-my.lazy
dir: { /* 指令定义对象 */ }
}常用自定义指令示例
1. v-loading(加载中)
app.directive('loading', {
mounted(el, binding) {
el.style.position = 'relative'
const mask = document.createElement('div')
mask.className = 'loading-mask'
mask.style.display = binding.value ? 'flex' : 'none'
el.appendChild(mask)
el._loadingMask = mask
},
updated(el, binding) {
if (el._loadingMask) {
el._loadingMask.style.display = binding.value ? 'flex' : 'none'
}
}
})2. v-debounce(防抖点击)
app.directive('debounce', {
mounted(el, binding) {
let timer = null
el.addEventListener('click', () => {
clearTimeout(timer)
timer = setTimeout(() => {
binding.value()
}, 500)
})
}
})
// <button v-debounce="handleClick">Click</button>3. v-permission(权限控制)
app.directive('permission', {
mounted(el, binding) {
if (!hasPermission(binding.value)) {
el.parentNode?.removeChild(el)
}
}
})
// <button v-permission="'admin'">删除</button>4. v-copy(复制到剪贴板)
app.directive('copy', {
mounted(el, binding) {
el.style.cursor = 'pointer'
el.addEventListener('click', () => {
navigator.clipboard.writeText(binding.value)
showToast('已复制')
})
}
})
// <span v-copy="text">{{ text }}</span>5. v-lazy(图片懒加载)
app.directive('lazy', {
mounted(el, binding) {
const observer = new IntersectionObserver(([entry]) => {
if (entry.isIntersecting) {
el.src = binding.value
observer.unobserve(el)
}
})
observer.observe(el)
el._observer = observer
},
unmounted(el) {
el._observer?.disconnect()
}
})
// <img v-lazy="imageSrc" />Vue3 变化
- 钩子名称改变:
bind→beforeMount,unbind→unmounted <script setup>中以v开头的变量自动识别为指令