摘要:例子修飾類(lèi)自定義參數(shù)值此例和上面功能基本一致,唯一差別在于值是參考修飾函數(shù)傳過(guò)來(lái)的例子修飾方法修飾函數(shù),對(duì)方法進(jìn)行只讀操作嘗試修改函數(shù),在控制臺(tái)會(huì)報(bào)錯(cuò)上例中,我們對(duì)類(lèi)中的方法使用修飾器進(jìn)行修飾,使得方法不能被修改。
什么是修飾器
修飾器(Decorator)是ES7的一個(gè)提案,它的出現(xiàn)能解決兩個(gè)問(wèn)題:
不同類(lèi)間共享方法
編譯期對(duì)類(lèi)和方法的行為進(jìn)行改變
用法也很簡(jiǎn)單,就是在類(lèi)或方法的上面加一個(gè)@符,在vue in typescript中經(jīng)常用到
以上的兩個(gè)用處可能不太明白,沒(méi)關(guān)系,我們開(kāi)始第一個(gè)例子
例子1:修飾類(lèi)@setProp class User {} function setProp(target) { target.age = 30 } console.log(User.age)
這個(gè)例子要表達(dá)的是對(duì)User類(lèi)使用setProp這個(gè)方法進(jìn)行修飾,用來(lái)增加User類(lèi)中age的屬性,setProp方法會(huì)接收3個(gè)參數(shù),我們現(xiàn)在接觸第一個(gè),target代表User類(lèi)本身。
例子2:修飾類(lèi)(自定義參數(shù)值)@setProp(20) class User {} function setProp(value) { return function (target) { target.age = value } } console.log(User.age)
此例和上面功能基本一致,唯一差別在于值是參考修飾函數(shù)傳過(guò)來(lái)的
例子2:修飾方法class User { @readonly getName() { return "Hello World" } } // readonly修飾函數(shù),對(duì)方法進(jìn)行只讀操作 function readonly(target, name, descriptor) { descriptor.writable = false return descriptor } let u = new User() // 嘗試修改函數(shù),在控制臺(tái)會(huì)報(bào)錯(cuò) u.getName = () => { return "I will override" }
上例中,我們對(duì)User類(lèi)中的getName方法使用readonly修飾器進(jìn)行修飾,使得方法不能被修改。第一個(gè)參數(shù)我們已經(jīng)知道了,參數(shù)name為方法名,也就是readonly,參數(shù)descriptor是個(gè)啥東西呢,看到這行descriptor.writable = false,我們大家猜的也差不多了,這三個(gè)參數(shù)對(duì)應(yīng)的就是Object.defineProperty的三個(gè)參數(shù),我們來(lái)看一下:
我們?cè)O(shè)置descriptor.writable = false就是讓函數(shù)不可以被修改,如果我們寫(xiě)成
descriptor.value = "function (){ console.log("Hello decorator") }"
那么,輸出就是Hello World了,而是Hello decorator,是不是已經(jīng)意識(shí)到修飾器的好處了?,F(xiàn)在我們來(lái)看看實(shí)際工作中,我們用到修飾器的例子
實(shí)際應(yīng)用1:日志管理在用webpack打包時(shí),我們經(jīng)常需要好多步驟,比如第一步讀取package.json文件,第二步處理該文件,第三步加載webpack.base.js文件,第四步進(jìn)行打包...為了直觀,我們經(jīng)常在每一步打印一些日志文件,比如這步都干了些什么事,很明顯打印日志的操作和業(yè)務(wù)代碼根本就一點(diǎn)關(guān)系沒(méi)有,我們不應(yīng)該把日志和業(yè)務(wù)摻和在一起,這樣使用修飾器就是避免這個(gè)問(wèn)題,以下為代碼:
class Pack { @log("讀取package.json文件") step1() { // do something... // 沒(méi)有修飾器之前,我們通常把console.log放到這里寫(xiě) // 放到函數(shù)里面寫(xiě)會(huì)有兩個(gè)壞處 // 1.console和業(yè)務(wù)無(wú)關(guān),會(huì)破壞函數(shù)單一性原則 // 2.如果要?jiǎng)h除所有的console,那我們只能深入到每一個(gè)方法中 } @log("合并webpack配置文件") step2() { // do something... } } function log(value) { return function (target, name, descriptor) { // 在這里,我們還可以拿到函數(shù)的參數(shù),打印更加詳細(xì)的信息 console.log(value) } } let pack = new Pack() pack.step1() pack.step2()實(shí)際應(yīng)用2:檢查登錄
這個(gè)例子在實(shí)際的開(kāi)發(fā)中常用得到,我們一些操作前,必須得判斷用戶是否登錄,比較點(diǎn)贊、結(jié)算、發(fā)送彈幕...按照之前的寫(xiě)法,我們必須在每一個(gè)方法中判斷用戶的登錄情況,然后再進(jìn)行業(yè)務(wù)的操作,很顯然前置條件和業(yè)務(wù)又混到了一起,用修飾器,就可以完美的解決這一問(wèn)題,代碼如下:
class User { // 獲取已登錄用戶的用戶信息 @checkLogin getUserInfo() { /** * 之前,我們都會(huì)這么寫(xiě): * if(checkLogin()) { * // 業(yè)務(wù)代碼 * } * 這段代碼會(huì)在每一個(gè)需要登錄的方法中執(zhí)行 * 還是上面的問(wèn)題,執(zhí)行的前提和業(yè)務(wù)又混到了一起 */ console.log("獲取已登錄用戶的用戶信息") } // 發(fā)送消息 @checkLogin sendMsg() { console.log("發(fā)送消息") } } // 檢查用戶是否登錄,如果沒(méi)有登錄,就跳轉(zhuǎn)到登錄頁(yè)面 function checkLogin(target, name, descriptor) { let method = descriptor.value // 模擬判斷條件 let isLogin = true descriptor.value = function (...args) { if (isLogin) { method.apply(this, args) } else { console.log("沒(méi)有登錄,即將跳轉(zhuǎn)到登錄頁(yè)面...") } } } let u = new User() u.getUserInfo() u.sendMsg()結(jié)語(yǔ)
以上只是修飾器的基本應(yīng)用,只要我們掌握了原理,在實(shí)際的工作中,要思考自己的應(yīng)用場(chǎng)景,只要我們涉及需要在執(zhí)行前做一些處理的應(yīng)用,不管是修改函數(shù)的參數(shù)值,還是增加屬性,還是執(zhí)行的先決條件,我們都可以使用修飾器,這種編程的方式,就是面向切面編程
源碼以及使用方法,請(qǐng)移步GitHub文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/88933.html
摘要:修飾器是一個(gè)函數(shù),用于修改類(lèi)行為。結(jié)論以上只是一個(gè)很簡(jiǎn)單的修飾器示例,你可以根據(jù)需要生產(chǎn)一些有意思的修飾器,讓編寫(xiě)的代碼更優(yōu)雅更干凈。 一般在JavaScript中為了讓部分代碼延遲執(zhí)行,一想起的自然是 setTimeout,比如: setTimeout(() => { // doing }, 0); 這種代碼或許你不知道寫(xiě)過(guò)多少遍,但,我們?cè)?setTimeout 中多數(shù)情況下會(huì)...
摘要:下裝飾者的實(shí)現(xiàn)了解了裝飾者模式和的概念之后,我們寫(xiě)一段能夠兼容的代碼來(lái)實(shí)現(xiàn)裝飾者模式原函數(shù)拍照片定義函數(shù)裝飾函數(shù)加濾鏡用裝飾函數(shù)裝飾原函數(shù)這樣我們就實(shí)現(xiàn)了抽離拍照與濾鏡邏輯,如果以后需要自動(dòng)上傳功能,也可以通過(guò)函數(shù)來(lái)添加。 showImg(https://segmentfault.com/img/bVbueyz?w=852&h=356); 什么是裝飾者模式 當(dāng)我們拍了一張照片準(zhǔn)備發(fā)朋友...
ES6 Decorators(修飾器) 修飾器(Decorator)是一個(gè)函數(shù),用來(lái)修改類(lèi)的行為。這是ES7的一個(gè)提案,目前Babel轉(zhuǎn)碼器已經(jīng)支持 我們?cè)谟螒虼笮晚?xiàng)目種經(jīng)常會(huì)用到的方法,現(xiàn)在es6直接支持 想要使用Decorator的話需要我們配置一下文件夾,配置一下環(huán)境 npm install babel-plugin-transform-decorators-legacy --save-de...
摘要:前言今天閑來(lái)時(shí)看了看中的新標(biāo)準(zhǔn)之一,裝飾器。過(guò)程中忽覺(jué)它和中的注解有一些類(lèi)似之處,并且當(dāng)前版本的中已經(jīng)支持它了,所以,就動(dòng)手在一個(gè)應(yīng)用中嘗鮮初體驗(yàn)了一番。另外,由于裝飾器目前還是中的一個(gè)提案,其中具體細(xì)節(jié)可能還會(huì)更改。 前言 今天閑來(lái)時(shí)看了看ES7中的新標(biāo)準(zhǔn)之一,裝飾器(Decorator)。過(guò)程中忽覺(jué)它和Java中的注解有一些類(lèi)似之處,并且當(dāng)前版本的TypeScript中已經(jīng)支持它了...
摘要:為了代碼進(jìn)一步解耦,可以考慮使用高階組件這種模式。開(kāi)源的高階組件使用提供了一系列使用的高階組件,可以增強(qiáng)組件的行為,可以利用此庫(kù)學(xué)習(xí)高階組件的寫(xiě)法。通過(guò)使用此庫(kù)提供的高階組件,可以方便地讓列表元素可拖動(dòng)。 1. Decorator基本知識(shí) 在很多框架和庫(kù)中看到它的身影,尤其是React和Redux,還有mobx中,那什么是裝飾器呢。 修飾器(Decorator)是一個(gè)函數(shù),用來(lái)修改類(lèi)的...
閱讀 949·2021-09-07 09:58
閱讀 1496·2021-09-07 09:58
閱讀 2892·2021-09-04 16:40
閱讀 2511·2019-08-30 15:55
閱讀 2419·2019-08-30 15:54
閱讀 1376·2019-08-30 15:52
閱讀 441·2019-08-30 10:49
閱讀 2612·2019-08-29 13:21