Decorator 是一種透過註解表達式就可以擴充類別或方法的函數。 Decorator 可以套用在任何一個 class 或property 上。列如:
@myDecorator class A {} // 作用class @myDecorator doSomething() {} // 作用表达式
Javascript Decorator 目前任然是ES7提案狀態,更多此特性的進度可以存取 proposal-decorators 查看。
說到更改物件的屬性或方法,大家一定會想到Object.defineProperty(obj, prop, descriptor) 方法,透過該方法,我們可以輕易的修改或者重寫物件的行為或屬性,先前Vue 中提到的雙向綁定,即是透過重寫set 和get 方法來實現的。所以在我們還未正式用上 Decorator 前,都是透過 Object.defineProperty 方法來實現。先來簡單的認識下這個方法:
/**
obj : 需要修改屬性的物件
#prop : 需要修改物件的屬性名稱
descriptor: 用來定義屬性具體行為的描述物件
**/
Object.defineProperty(obj, prop, descriptor)
descriptor 屬性說明
configurable : 定義屬性物件是否可以被配置,也就是如果為false ,定義修改的描述操作(writeable, get 等等)都無效
#enumerable : 是否可以透過for-in 來遍歷,或者Object.keys 列舉
value : 定義物件value 屬性的值,value 可以是number, object, function 等等
writable: 定義value 值是否可以被重寫
get: 一個存取value 屬性時會觸發的function 物件
set: 一個設定value 屬性時會觸發的function 物件
修改一個屬性為唯讀(readonly)
了解Object .defineProperty 的基本語法後,我透過它先簡單實作一個readonly 實例。具體程式碼如下:
``javascript # 定义 function myDecoration(target, name, descriptor) {} # 对property使用 class A { @myDecorator test() {} } # 对class使用 @myDecorator class A {} # 带参数 function myDescorator(a) { return function (target, name, descriptor) { console.llog('params:', a) } } @myDescorator(a) class A {} # 时使用多个装饰器(Decorator) @myDecorator1 @myDecorator2 class A {}
利用Decorator 語法糖修改一個屬性為唯讀法(readonly)
我們都知道,在React 生命週期裡有一個shouldComponentUpdate 方法,該方法透過返回ture 或false 來確定元件是否重新render 元件。也就是說,透過這個方法我們可以過濾掉些無效的資料渲染事件,進而提升效能。例如我們針對 props 傳遞過來的資料物件進行對比,如果 props 物件的屬性以及值並未變更的情況下,則無需執行render方法。
顯然透過比較 props 下資料物件的屬性與值是否變更,這種邏輯是可以重複使用的,而不是在單獨的在每個元件中去在重複的寫 shouldComponentUpdate 方法。說到改變元件物件的方法行為,這裡我們顯然就可以使用
Decorator 來這個特性來做了,也就是我們對應用 Decorator 物件的 shouldComponentUpdate 進行重寫。透過遍歷 props 物件的屬性和值,並與舊 props 的屬性與值進行對比,從而確定是否需要重新渲染。具體代碼如下:
function isEqual(a, b) { for (const key in a) { if ({}.hasOwnProperty.call(a, key) && (!{}.hasOwnProperty.call(b, key) || a[key] !== b[key])) { return false; } } for (const key in b) { if ({}.hasOwnProperty.call(b, key) && !{}.hasOwnProperty.call(a, key)) { return false; } } return true; } export default function pureRender(targetComponent) { targetComponent.prototype.shouldComponentUpdate = function (props, state) { return !isEqual(this.state, state) || !isEqual(this.props, props) } } // 使用 @pureRender class ComponentA extends React.Component {}
由於 Decorator 是ES7中的草案,現在需要透過 Bable 才能使用。使用方法如下:
安裝
npm install --save-dev babel-plugin-transform-decorators
使用
方法一、透過設定.babelrc
{ "plugins": ["transform-decorators"] }
方法二、透過CLI
babel --plugins transform-decorators script.js
方法三、透過Node API
require("babel-core").transform("code", { plugins: ["transform-decorators"] });
透過Decorator 這種不需要直接在物件或方法中寫額外邏輯的方式,就可以輕易的擴充物件或方法的能力,既滿足了功能需求,也精簡了程式碼,保證了程式碼的可維護性,例如我們已經常見的@log, @test, @mixin等等工具類。所以,以後的工作可以多嘗試。
細說ES7 JavaScript Decorators
Decorator specification
Exploring EcmaScript Decorators
Object.defineProperty
Babel Legacy Decorator plugin
#core-decorators
以上內容就是Decorator 簡介及相關教學課程,希望能幫助大家。
先關推薦:
#以上是Decorator 簡介及相關教學課程的詳細內容。更多資訊請關注PHP中文網其他相關文章!