Vue框架TypeScript裝飾器使用指南小結(jié)
前言
裝飾器是一種特殊類型的聲明,它能夠被附加到 類聲明,方法, 訪問符,屬性或參數(shù) 上。 裝飾器使用 @expression這種形式, expression求值 后必須為一個(gè)函數(shù),它會(huì)在 運(yùn)行時(shí)被調(diào)用 ,被裝飾的聲明信息做為參數(shù)傳入。
本篇先從項(xiàng)目的宏觀角度來總結(jié)一下Decorator如何組織。
目錄
- 主要的Decorator依賴
- vue-class-component
- vuex-class
- vue-property-decorator
- core-decorators
- 自定義Decorator示例
- 哪些功能適合用Decorator實(shí)現(xiàn)
- Decorator實(shí)現(xiàn)小Tips
- See also
主要的Decorator依賴
vue-cli3 默認(rèn)支持Decorator, 年初重寫了一個(gè)design庫主要依賴官方和社區(qū)提供的Decorator來實(shí)現(xiàn)的組件。 Decorator可以非侵入的裝飾類、方法、屬性,解耦業(yè)務(wù)邏輯和輔助功能邏輯。以下是主要的三方Decorator組件:
vue-class-component
- @Component 如果您在聲明組件時(shí)更喜歡基于類的 API,則可以使用官方維護(hù)的 vue-class-component 裝飾器
- 實(shí)時(shí)計(jì)算computed屬性, get computedMsg () {return 'computed ' + this.msg}
- 生命周期鉤子 mounted () {this.greet()}
vuex-class
讓Vuex和Vue之間的綁定更清晰和可拓展
- @State
- @Getter
- @Action
- @Mutation
vue-property-decorator
這個(gè)組件完全依賴于vue-class-component.它具備以下幾個(gè)屬性:
- @Component (完全繼承于vue-class-component)
- @Prop:父子組件之間值的傳遞
- @Emit:子組件向父組件傳遞
- @Model:雙向綁定
- @Watch:觀察的表達(dá)式變動(dòng)
- @Provice:在組件嵌套層級(jí)過深時(shí)。父組件不便于向子組件傳遞數(shù)據(jù)。就把數(shù)據(jù)通過Provide傳遞下去。
- @Inject:然后子組件通過Inject來獲取
- Mixins (在vue-class-component中定義);
core-decorators
- @readonly
- @autobind : TSX 回調(diào)函數(shù)中的 this,類的方法默認(rèn)是不會(huì)綁定 this 的,可以使用autobind裝飾器
- @override
總結(jié)一下主要就分成這三類:
- 修飾類的:@Component、@autobind;
- 修飾方法的:@Emit、@Watch、@readonly、@override;
- 修飾屬性的:@Prop、@readonly;
以上引用方法等詳系內(nèi)容可查看官方文檔。下面自定義部分來實(shí)現(xiàn)一個(gè)記錄日志功能的裝飾器。
自定義Decorator示例
@Logger,Logger日志裝飾器通常是修飾方法,Decorater則是在 運(yùn)行時(shí)就被觸發(fā)了 ,日志記錄是在 方法被調(diào)用時(shí)觸發(fā) ,示例中通過自動(dòng)發(fā)布事件實(shí)現(xiàn)調(diào)用時(shí)觸發(fā)。為增加日志記錄的靈活性,需要通過暴露鉤子函數(shù)的方式來改變?nèi)罩居涗浀膬?nèi)容。
期望的日志格式
{ "logId":"", // 事件Id "input":"", // 方法輸入的內(nèi)容 "output":"", // 方法輸出的內(nèi)容 "custom":"" // 自定義的日志內(nèi)容 }
實(shí)現(xiàn)
export function Logger(logId?: string, hander?: Function) { const loggerInfo =Object.seal({logId:logId, input:'',output:'', custom: ''}); const channelName = '__logger'; const msgChannel = postal.channel(channelName); msgChannel.subscribe(logId, logData => { // 根據(jù)業(yè)務(wù)邏輯來處理日志 console.log(logData); }); return function (target: any, key: string, descriptor: TypedPropertyDescriptor<any>): TypedPropertyDescriptor<any> { const oldValue = descriptor.value descriptor.value = function () { const args: Array<any> = []; for (let index in arguments) { args.push(arguments[index]); } loggerInfo.input = `${key}(${args.join(',')})`; // 執(zhí)行原方法 const value = oldValue.apply(this, arguments); loggerInfo.output = value; hander && (loggerInfo.custom = hander(loggerInfo.input, loggerInfo.output) || ''); // 被調(diào)用時(shí),會(huì)自動(dòng)發(fā)出一個(gè)事件 msgChannel.publish(logId, loggerInfo); } return descriptor } }
使用
@Logger('event_get_detial1') getDetial(id?: string, category?: string) { return "詳細(xì)內(nèi)容"; } // 或者 @Logger('event_get_detial2', (input, output) => { return '我是自定義內(nèi)容'; }) getDetial2(id?: string, category?: string) { return "詳細(xì)內(nèi)容"; } ... <button @click="getDetial2('1000', 'a')">獲取詳情</button>
效果: {logId: "event_get_detial2", input: "getDetial(1000,a)", output: "詳細(xì)內(nèi)容", custom: "我是自定義內(nèi)容"} , 每次點(diǎn)擊按鈕都會(huì)觸發(fā)一次。
TODO: 這里還需要對(duì)輸入?yún)?shù)和輸出參數(shù)中的引用數(shù)據(jù)類型做處理。
同時(shí)還需要掌握: 裝飾器工廠、裝飾器組合、裝飾器求值、參數(shù)裝飾器、元數(shù)據(jù)
哪些功能適合用Decorator實(shí)現(xiàn)
官網(wǎng)和社區(qū)提供的這些Decorator, 可以作為自己框架的底層設(shè)計(jì)。
日志功能全局都得用,調(diào)用方法基本一致,是最適合使用裝飾器來實(shí)現(xiàn),并且每個(gè)項(xiàng)目的日志記錄各有差異,最適合自定義這部分。
Decorator實(shí)現(xiàn)小Tips
- 考慮下各類Decorator疊加和共存的問題,可以參考官網(wǎng)關(guān)于裝飾器組合描述
- Decorator 的目標(biāo)是在原有功能基礎(chǔ)上,添加功能,切忌覆蓋原有功能
- 類裝飾器不能用在聲明文件中( .d.ts),也不能用在任何外部上下文中(比如declare的類)
- 裝飾器只能用于類和類的方法,不能用于函數(shù),因?yàn)榇嬖诤瘮?shù)提升。類是不會(huì)提升的,所以就沒有這方面的問題。
- 注意遷移速度、避免一口吃成胖子的做法
- 不要另起爐灶對(duì)主流庫創(chuàng)建Decorator庫,主流庫維護(hù)成本很高還是得有官方來維護(hù),為保證質(zhì)量不使用個(gè)人編寫的Decorator庫。自己在創(chuàng)建Decorator庫時(shí)也要有這個(gè)意識(shí),僅做一些有必要自定義的。
- Decorator 不是管道模式,decorator之間不存在交互,所以必須注意保持decorator獨(dú)立性、透明性
- Decorator 更適用于非業(yè)務(wù)功能需求
- 確定 decorator 的用途后,切記執(zhí)行判斷參數(shù)類型
- decorator 針對(duì)每個(gè)裝飾目標(biāo),僅執(zhí)行一次
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
深入淺出 Vue 系列 -- 數(shù)據(jù)劫持實(shí)現(xiàn)原理
深入淺出 Vue 系列 -- 數(shù)據(jù)劫持實(shí)現(xiàn)原理2019-04-04在nuxt使用vueX代替storage的實(shí)現(xiàn)方案
這篇文章主要介紹了在nuxt使用vueX代替storage的實(shí)現(xiàn)方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-10-10Vue列表循環(huán)從指定下標(biāo)開始的多種解決方案
這篇文章主要介紹了Vue列表循環(huán)從指定下標(biāo)開始的多種方案,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-04-04關(guān)于axios配置多個(gè)請(qǐng)求地址(打包后可通過配置文件修改)
這篇文章主要介紹了關(guān)于axios配置多個(gè)請(qǐng)求地址(打包后可通過配置文件修改),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-09-09Vue組件開發(fā)之LeanCloud帶圖形校驗(yàn)碼的短信發(fā)送功能
Vue是目前使用較廣泛的三大前端框架之一,其數(shù)據(jù)驅(qū)動(dòng)及組件化的特性使得前端開發(fā)更為快捷便利。本文在LeanCloud 短信轟炸與圖形校驗(yàn)碼官方文檔 基礎(chǔ)上,從封裝需要出發(fā)開發(fā)一個(gè)簡(jiǎn)單的短信圖形驗(yàn)證Vue組件,具體內(nèi)容詳情大家參考下本文2017-11-11Vue實(shí)現(xiàn)在線預(yù)覽pdf文件功能(利用pdf.js/iframe/embed)
項(xiàng)目要求需要預(yù)覽pdf文件,網(wǎng)上找了很久,發(fā)現(xiàn)pdf.js的效果,這篇文章主要給大家介紹了關(guān)于Vue實(shí)現(xiàn)在線預(yù)覽pdf文件功能,主要利用pdf.js/iframe/embed來實(shí)現(xiàn)的,需要的朋友可以參考下2021-06-06Vue實(shí)現(xiàn)簡(jiǎn)單網(wǎng)頁計(jì)算器
這篇文章主要為大家詳細(xì)介紹了Vue實(shí)現(xiàn)簡(jiǎn)單網(wǎng)頁計(jì)算器,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-04-04