10個(gè)Vue項(xiàng)目必備的高頻實(shí)用自定義指令(復(fù)制即用)
在實(shí)際開發(fā)中,很多重復(fù)邏輯(權(quán)限控制、防抖點(diǎn)擊、圖片懶加載、文本復(fù)制等)用自定義指令來做最優(yōu)雅,不污染組件、不寫冗余代碼、復(fù)用性極強(qiáng)。
今天整理了 10 個(gè)企業(yè)級最常用的 Vue 自定義指令,Vue2 / Vue3 都能跑,復(fù)制到項(xiàng)目里直接用,建議收藏進(jìn)你的工具庫。
1. v-permission 按鈕權(quán)限控制(后臺系統(tǒng)必用)
根據(jù)權(quán)限碼控制按鈕顯隱,后端返回權(quán)限列表直接用。
// directives/permission.js
import { useUserStore } from '@/stores/user'
export default {
mounted(el, binding) {
const { permissions } = useUserStore()
const value = binding.value
if (!value) return
// 無權(quán)限則移除元素
if (!permissions.includes(value)) {
el.parentNode?.removeChild(el)
}
}
}
使用:
<button v-permission="'user:add'">添加用戶</button>
2. v-debounce 防抖點(diǎn)擊(搜索/提交防重復(fù))
// directives/debounce.js
export default {
mounted(el, binding) {
const { func, delay = 300 } = binding.value
let timer = null
el.addEventListener('click', () => {
clearTimeout(timer)
timer = setTimeout(() => func(), delay)
})
}
}
使用:
<button v-debounce="{ func: handleSearch, delay: 500 }">搜索</button>3. v-throttle 節(jié)流指令(滾動(dòng)/防狂點(diǎn))
// directives/throttle.js
export default {
mounted(el, binding) {
const { func, delay = 500 } = binding.value
let lastTime = 0
el.addEventListener('click', () => {
const now = Date.now()
if (now - lastTime >= delay) {
func()
lastTime = now
}
})
}
}
4. v-copy 一鍵復(fù)制文本
// directives/copy.js
export default {
mounted(el, binding) {
el.addEventListener('click', () => {
const text = binding.value
navigator.clipboard.writeText(text).then(() => {
ElMessage.success('復(fù)制成功')
})
})
}
}
使用:
<span v-copy="orderNo">復(fù)制訂單號</span>
5. v-longpress 長按指令
// directives/longpress.js
export default {
mounted(el, binding) {
const { func, time = 1000 } = binding.value
let timer = null
el.addEventListener('mousedown', () => {
timer = setTimeout(() => func(), time)
})
el.addEventListener('mouseup mouseleave', () => clearTimeout(timer))
}
}
6. v-input-number 僅允許輸入數(shù)字(支持小數(shù))
// directives/number.js
export default {
mounted(el) {
const input = el.tagName === 'INPUT' ? el : el.querySelector('input')
input.addEventListener('input', () => {
input.value = input.value.replace(/[^\d.]/g, '')
const arr = input.value.split('.')
if (arr.length > 2) input.value = arr[0] + '.' + arr[1]
})
}
}
使用:
<el-input v-input-number v-model="num" />
7. v-lazy 圖片懶加載(性能優(yōu)化)
// directives/lazy.js
export default {
mounted(el, binding) {
const observer = new IntersectionObserver(([{ isIntersecting }]) => {
if (isIntersecting) {
el.src = binding.value
observer.unobserve(el)
}
})
observer.observe(el)
}
}
使用:
<img v-lazy="imgUrl" alt="" />
8. v-draggable 元素拖拽
// directives/drag.js
export default {
mounted(el) {
el.style.cssText += ';position:fixed;cursor:move;'
el.addEventListener('mousedown', (e) => {
const x = e.clientX - el.offsetLeft
const y = e.clientY - el.offsetTop
const move = (e) => {
el.style.left = e.clientX - x + 'px'
el.style.top = e.clientY - y + 'px'
}
document.addEventListener('mousemove', move)
document.addEventListener('mouseup', () => {
document.removeEventListener('mousemove', move)
}, { once: true })
})
}
}
9. v-watermark 頁面水印(防截圖)
// directives/watermark.js
export default {
mounted(el, binding) {
const text = binding.value || '內(nèi)部資料'
const canvas = document.createElement('canvas')
canvas.width = 200
canvas.height = 150
const ctx = canvas.getContext('2d')
ctx.font = '14px Arial'
ctx.fillStyle = 'rgba(0,0,0,0.1)'
ctx.rotate(-0.2)
ctx.fillText(text, 20, 50)
el.style.background = `url(${canvas.toDataURL()}) repeat`
}
}
10. v-auto-height 自適應(yīng)高度(表格/彈窗常用)
自動(dòng)計(jì)算高度,避免滾動(dòng)條錯(cuò)亂
// directives/autoHeight.js
export default {
mounted(el) {
const resize = () => {
const top = el.getBoundingClientRect().top
el.style.height = window.innerHeight - top - 20 + 'px'
}
resize()
window.addEventListener('resize', resize)
el._resize = resize
},
unmounted(el) {
window.removeEventListener('resize', el._resize)
}
}
統(tǒng)一注冊(Vue3)
在 directives/index.js 統(tǒng)一導(dǎo)出:
import permission from './permission'
import debounce from './debounce'
// ...其他
export default {
install(app) {
app.directive('permission', permission)
app.directive('debounce', debounce)
}
}
main.js 引入:
import directives from '@/directives' app.use(directives)
到此這篇關(guān)于10個(gè)Vue項(xiàng)目必備的高頻實(shí)用自定義指令(復(fù)制即用)的文章就介紹到這了,更多相關(guān)Vue自定義指令內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
為vue項(xiàng)目自動(dòng)設(shè)置請求狀態(tài)的配置方法
這篇文章主要介紹了vue項(xiàng)目自動(dòng)設(shè)置請求狀態(tài)的配置方法,本文通過示例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-06-06
基于Vue3+Node.js實(shí)現(xiàn)客服實(shí)時(shí)聊天功能
想象一下淘寶客服的聊天窗口:你發(fā)消息,客服立刻就能看到并回復(fù),這種即時(shí)通訊效果是如何實(shí)現(xiàn)的呢?本文我們使用 Vue3 作為前端框架,Node.js 作為后端,通過 WebSocket+ Socket.IO 協(xié)議實(shí)現(xiàn)實(shí)時(shí)通信,需要的朋友可以參考下2025-05-05
Vue使用Echarts實(shí)現(xiàn)橫向柱狀圖,并通過WebSocket即時(shí)通訊更新
這篇文章主要介紹了Vue使用Echarts實(shí)現(xiàn)橫向柱狀圖,并通過WebSocket即時(shí)通訊更新方式,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-03-03

