vue3.x lodash在項(xiàng)目中管理封裝指令的優(yōu)雅使用
vue3.x directives
vue 指令是一種特殊的 vue.js 特性,用于在 DOM 元素上添加特定的行為或功能。指令通過(guò)在元素上使用特定的指令名稱和參數(shù)來(lái)實(shí)現(xiàn),可以用于操作 DOM、響應(yīng)事件、綁定數(shù)據(jù)等。今天簡(jiǎn)述一下如何在項(xiàng)目中優(yōu)雅的管理、封裝一些常用的指令。
后面代碼基本上會(huì)逐行進(jìn)行注釋,以便于大家閱讀。
管理指令
統(tǒng)一管理
- 統(tǒng)一包管理:通過(guò)創(chuàng)建
directives文件夾,我們可以將所有與指令相關(guān)的文件集中在一個(gè)位置,使其更易于查找和維護(hù)。這種統(tǒng)一的包管理結(jié)構(gòu)有助于組織和管理指令相關(guān)的代碼。 - 模塊化指令:在
directives/modules文件夾中,我們?yōu)槊總€(gè)指令創(chuàng)建一個(gè)獨(dú)立的文件夾。這種模塊化的結(jié)構(gòu)使每個(gè)指令的邏輯和功能被封裝在一個(gè)獨(dú)立的文件中,方便單獨(dú)管理和維護(hù)。每個(gè)指令文件夾中的出口文件index.ts可以用于導(dǎo)出指令邏輯,使其在項(xiàng)目中得以統(tǒng)一注冊(cè)和使用。 - 規(guī)范化命名:指令文件夾的命名需要言簡(jiǎn)意賅,能夠清晰表達(dá)指令的用途。通過(guò)規(guī)范化的命名,可以使項(xiàng)目中的指令更易于理解和識(shí)別,提高代碼的可讀性和可維護(hù)性。
- 可擴(kuò)展性:通過(guò)這種管理方式,我們可以輕松地添加新的指令。只需在 directives/modules 文件夾中創(chuàng)建一個(gè)新的指令文件夾,并在其中編寫相應(yīng)的指令邏輯即可。這種結(jié)構(gòu)使項(xiàng)目具有良好的可擴(kuò)展性,方便我們根據(jù)需要添加、修改或刪除指令。
· ├── directives ├──├── index.ts ├──├── modules ├──├──├── some directive ├──├──├──├── index.ts type.ts ...
統(tǒng)一注冊(cè)
每個(gè)指令都使用 index.ts 文件統(tǒng)一暴露一個(gè) CustomDirectiveFC 類型的函數(shù),并且在根目錄的 index.ts 中自動(dòng)搜集 modules 文件夾中的所有文件并注冊(cè)這些指令。
公共類型(type.ts)
import type { Directive } from 'vue'
import type { App } from 'vue'
export type { DebounceBindingOptions } from './modules/debounce/type'
export type { ThrottleBindingOptions } from './modules/throttle/type'
export type CustomDirectiveFC<T, K> = () => Directive<T, K>
export interface DirectiveModules extends Object {
default: CustomDirectiveFC<unknown, unknown>
}
export type AppType = App<Element>搜集、注冊(cè)指令
利用 import.meta.glob 方法(如果是 webpack 則是使用 require.context),獲取所有指令文件夾的路徑。然后,遍歷這些文件夾,找到包含 index.ts 文件的位置。在每個(gè) index.ts 文件中,你可以導(dǎo)入 CustomDirectiveFC 函數(shù)。通過(guò)這種方式,你可以自動(dòng)搜集所有指令,并進(jìn)行注冊(cè)。
警告
該方式會(huì)搜集 modules 中所有的文件夾,并且以文件名稱作為指令名稱。如果是多個(gè)單詞,請(qǐng)使用小寫單詞并以 - 連接。
import type { DirectiveModules, CustomDirectiveFC } from '@/directives/type'
export const combineDirective = <
T extends Record<string, DirectiveModules>,
K extends keyof T,
>(
directiveModules: T,
) => {
const directives = Object.keys(directiveModules).reduce((pre, curr) => {
const fc = directiveModules[curr]?.default
if (typeof fc === 'function') {
pre[curr] = fc
return pre
} else {
throw new Error('directiveModules[curr] is not function')
}
}, {} as Record<K, CustomDirectiveFC<unknown, unknown>>)
return directives
}import { combineDirective } from './helper/combine'
import { forIn } from 'lodash-es'
import type { App } from 'vue'
import type { DirectiveModules } from '@/directives/type'
/**
*
* 初始化全局自定義指令
*
* 該方法會(huì)將 modules 下每個(gè)文件夾視為一個(gè)指令
* 并且會(huì)將文件夾名稱識(shí)別為指令名稱
* 每個(gè)文件下的 index.ts 文件視為每個(gè)指令的入口(也就是指令的處理邏輯, 需要暴露出一個(gè) Directive 類型的對(duì)象)
*/
export const setupDirectives = (app: App<Element>) => {
// 獲取 modules 包下所有的 index.ts 文件
const directiveRawModules: Record<string, DirectiveModules> =
import.meta.glob('@/directives/modules/**/index.ts', {
eager: true,
})
// 將所有的包提取出來(lái)(./modules/[file-name]/index.ts)
const directivesModules = combineDirective(directiveRawModules)
// 提取文件名(./modules/copy/index.ts => copy)
const regexExtractDirectiveName = /(?<=modules\/).*(?=\/index\.ts)/
// 匹配合法指令名稱
const regexDirectiveName = /^([^-]+-)*[^-]+$/
forIn(directivesModules, (value, key) => {
const dname = key.match(regexExtractDirectiveName)?.[0]
if (typeof dname === 'string' && regexDirectiveName.test(dname)) {
app.directive(dname, value?.())
} else {
console.error(`[setupDirectives] ${dname} is not a valid directive name`)
}
})
}在 main.ts 文件中導(dǎo)入并且調(diào)用 setupDirectives 方法,即可完成自定義指令的搜集與注冊(cè)。然后即可在項(xiàng)目全局中使用。
自定義指令
準(zhǔn)備工作我們已經(jīng)完成了,現(xiàn)在只需要開(kāi)發(fā)自定義指令即可?,F(xiàn)在我們來(lái)封裝幾個(gè)常用指令熱熱手。
v-throttle
實(shí)現(xiàn)
import type { ThrottleSettings } from 'lodash-es'
import type { AnyFC } from '@/types/modules/utils'
export interface ThrottleBindingOptions {
func: AnyFC
trigger?: string
wait?: number
options?: ThrottleSettings
}import { throttle } from 'lodash-es'
import { on, off } from '@use-utils/element'
import type { ThrottleBindingOptions } from './type'
import type { AnyFC } from '@/types/modules/utils'
import type { DebouncedFunc } from 'lodash-es'
import type { CustomDirectiveFC } from '@/directives/type'
const throttleDirective: CustomDirectiveFC<
HTMLElement,
ThrottleBindingOptions
> = () => {
let throttleFunction: DebouncedFunc<AnyFC> | null
return {
beforeMount: (el, { value }) => {
const { func, trigger = 'click', wait = 500, options } = value
if (typeof func !== 'function') {
throw new Error('throttle directive value must be a function')
}
throttleFunction = throttle(func, wait, Object.assign({}, options))
on(el, trigger, throttleFunction)
},
beforeUnmount: (el, { value }) => {
const { trigger = 'click' } = value
if (throttleFunction) {
throttleFunction.cancel()
off(el, trigger, throttleFunction)
}
throttleFunction = null
},
}
}
export default throttleDirective使用
<template>
<p>我執(zhí)行了{(lán){ count }}次</p>
<p>該方法 1s 內(nèi)僅會(huì)執(zhí)行一次</p>
<button
v-throttle="{
func: handleClick,
trigger: 'click',
wait: 1000,
options: {},
}"
>
節(jié)流按鈕
</button>
</template>
<script setup lang="ts">
const count = ref(0)
const handleClick = () => {
count.value++
}
</script>v-debounce
實(shí)現(xiàn)
import type { DebounceSettings } from 'lodash-es'
import type { AnyFC } from '@/types/modules/utils'
export interface DebounceBindingOptions {
func: AnyFC
trigger?: string
wait?: number
options?: DebounceSettings
}import { debounce } from 'lodash-es'
import { on, off } from '@use-utils/element'
import type { DebounceBindingOptions } from './type'
import type { AnyFC } from '@/types/modules/utils'
import type { DebouncedFunc } from 'lodash-es'
import type { CustomDirectiveFC } from '@/directives/type'
const debounceDirective: CustomDirectiveFC<
HTMLElement,
DebounceBindingOptions
> = () => {
let debounceFunction: DebouncedFunc<AnyFC> | null
return {
beforeMount: (el, { value }) => {
const { func, trigger = 'click', wait = 500, options } = value
if (typeof func !== 'function') {
throw new Error('debounce directive value must be a function')
}
debounceFunction = debounce(func, wait, Object.assign({}, options))
on(el, trigger, debounceFunction)
},
beforeUnmount: (el, { value }) => {
const { trigger = 'click' } = value
if (debounceFunction) {
debounceFunction.cancel()
off(el, trigger, debounceFunction)
}
debounceFunction = null
},
}
}
export default debounceDirective使用
<template>
<p>我執(zhí)行了{(lán){ count }}次</p>
<p>該方法將延遲 1s 執(zhí)行</p>
<button
v-throttle="{
func: handleClick,
trigger: 'click',
wait: 1000,
options: {},
}"
>
防抖按鈕
</button>
</template>
<script setup lang="ts">
const count = ref(0)
const handleClick = () => {
count.value++
}
</script>自定義指令目錄結(jié)構(gòu)
· ├── directives ├──├── index.ts type.ts ├──├── modules ├──├──├── throttle ├──├──├──├── index.ts type.ts ├──├──├── debounce ├──├──├──├── index.ts type.ts
按照上述步驟以后,你將會(huì)得到這樣的一個(gè)目錄結(jié)構(gòu)。
最后
所有的代碼源碼都來(lái)自于 Ray Template,可以自行點(diǎn)擊查看源碼
以上就是vue3.x lodash在項(xiàng)目中管理封裝指令的優(yōu)雅使用的詳細(xì)內(nèi)容,更多關(guān)于vue3.x lodash管理封裝指令的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
element?ui富文本編輯器的使用效果與步驟(quill-editor)
富文本編輯器在任何項(xiàng)目中都會(huì)用到,在Element中我們推薦vue-quill-editor組件,下面這篇文章主要給大家介紹了關(guān)于element?ui富文本編輯器的使用效果與步驟(quill-editor)的相關(guān)資料,需要的朋友可以參考下2022-10-10
vue項(xiàng)目里面引用svg文件并給svg里面的元素賦值
這篇文章主要介紹了vue項(xiàng)目里面引用svg文件并給svg里面的元素賦值,本文分步驟通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-08-08
vuejs響應(yīng)用戶事件(如點(diǎn)擊事件)
本篇文章主要介紹了vuejs響應(yīng)用戶事件(如點(diǎn)擊),通過(guò)vuejs響應(yīng)用戶事件的技巧,具有一定的參考價(jià)值,有興趣的小伙伴們可以參考一下。2017-03-03
Vue如何實(shí)現(xiàn)文件預(yù)覽和下載功能的前端上傳組件
在Vue.js項(xiàng)目中,使用ElementUI的el-upload組件可以輕松實(shí)現(xiàn)文件上傳功能,通過(guò)配置組件參數(shù)和實(shí)現(xiàn)相應(yīng)的方法,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下2024-09-09
詳解Vue前端生產(chǎn)環(huán)境發(fā)布配置實(shí)戰(zhàn)篇
這篇文章主要介紹了詳解Vue前端生產(chǎn)環(huán)境發(fā)布配置實(shí)戰(zhàn)篇,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2019-05-05
Vue之版本升級(jí)后不兼容的問(wèn)題及解決過(guò)程
本文將探討 Vue 版本升級(jí)后常見(jiàn)的不兼容問(wèn)題,并提供相應(yīng)的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2025-03-03
vue中多個(gè)倒計(jì)時(shí)實(shí)現(xiàn)代碼實(shí)例
這篇文章主要介紹了vue中多個(gè)倒計(jì)時(shí)實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-03-03
vue $set 實(shí)現(xiàn)給數(shù)組集合對(duì)象賦值
這篇文章主要介紹了vue $set 實(shí)現(xiàn)給數(shù)組集合對(duì)象賦值方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-07-07

