西安網(wǎng)站制作公司排給公司做網(wǎng)站的公司
TypeScript 混入(Mixins)
混入(Mixins)是面向?qū)ο缶幊讨械囊粋€(gè)比較重要的概念。本節(jié)將會(huì)通過(guò)一個(gè)實(shí)例逐步介紹混入是如何在 TypeScript 中使用的。
1. 解釋
在 TypeScript 中,可以根據(jù)不同的功能定義多個(gè)可復(fù)用的類(lèi),它們將作為?mixins
。因?yàn)?extends
?只支持繼承一個(gè)父類(lèi),我們可以通過(guò)?implements
?來(lái)連接多個(gè)?mixins
,并且使用原型鏈連接子類(lèi)的方法和父類(lèi)的方法。
這就像組件拼合一樣,由一堆細(xì)粒度的?mixins
?快速搭建起一個(gè)功能強(qiáng)大的類(lèi)。
2. 簡(jiǎn)單的對(duì)象混入
先來(lái)看一個(gè)基礎(chǔ)例子:
let target = { a: 1, b: 1 }
let source1 = { a: 2, c: 3 }
let source2 = { b: 2, d: 4 }Object.assign(target, source1, source2)console.log(target) // { a: 2, b: 2, c: 3, d: 4 }
解釋:?通過(guò)?Object.assign()
?將?source1
?與?source2
?混入到?target
?上,并且替換了?target
?對(duì)象原有的屬性值。
3. TypeScript Mixins
先介紹一個(gè)前置知識(shí):?Object.getOwnPropertyNames()
?方法返回一個(gè)由指定對(duì)象的所有自身屬性的屬性名(包括不可枚舉屬性但不包括Symbol值作為名稱(chēng)的屬性)組成的數(shù)組。
3.1 代碼演示
下面的代碼演示了如何在 TypeScript 中使用混入:
// Disposable Mixin
class Disposable {isDisposed!: booleandispose() {this.isDisposed = true}
}// Activatable Mixin
class Activatable {isActive!: boolean;activate() {this.isActive = true}deactivate() {this.isActive = false}
}class SmartObject{constructor() {setInterval(() => console.log(this.isActive + " : " + this.isDisposed), 500)}interact() {this.activate()}// DisposableisDisposed: boolean = falsedispose!: () => void// ActivatableisActive: boolean = falseactivate!: () => voiddeactivate!: () => void
}
applyMixins(SmartObject, [Disposable, Activatable])let smartObj = new SmartObject()
setTimeout(() => smartObj.interact(), 2000)function applyMixins(derivedCtor: any, baseCtors: any[]) {baseCtors.forEach(baseCtor => {Object.getOwnPropertyNames(baseCtor.prototype).forEach(name => {derivedCtor.prototype[name] = baseCtor.prototype[name]})})
}
3.2 逐步解析這個(gè)例子
代碼里首先定義了兩個(gè)類(lèi),它們將做為 mixins。可以看到每個(gè)類(lèi)都只定義了一個(gè)特定的行為或功能。稍后我們使用它們來(lái)創(chuàng)建一個(gè)新類(lèi),同時(shí)具有這兩種功能。
// Disposable Mixin
class Disposable {isDisposed!: booleandispose() {this.isDisposed = true}
}// Activatable Mixin
class Activatable {isActive!: booleanactivate() {this.isActive = true}deactivate() {this.isActive = false}
}
下面使用?implements
?連接多個(gè)父類(lèi),需要在子類(lèi)里實(shí)現(xiàn)所有接口定義。
class SmartObject implements Disposable, Activatable {}
這么做是為將要 mixin 進(jìn)來(lái)的屬性/方法創(chuàng)建出占位屬性。這告訴編譯器這些成員在運(yùn)行時(shí)是可用的,這樣就能使用 mixin 帶來(lái)的便利,雖說(shuō)需要提前定義一些占位屬性。
// DisposableisDisposed: boolean = falsedispose!: () => void// ActivatableisActive: boolean = falseactivate!: () => voiddeactivate!: () => void
子類(lèi)對(duì)外暴露一個(gè)封裝后的 public 方法,方法的具體實(shí)現(xiàn)可以借助混入的 mixins 類(lèi)中的屬性/方法:
interact() {this.activate()}
最后,把 mixins 混入定義的類(lèi),完成全部實(shí)現(xiàn)部分。
applyMixins(SmartObject, [Disposable, Activatable])
applyMixins()
?方法借助?Object.getOwnPropertyNames()
?遍歷 mixins 上的所有屬性,并復(fù)制到目標(biāo)上去,把之前的占位屬性替換成真正的實(shí)現(xiàn)代碼。
function applyMixins(derivedCtor: any, baseCtors: any[]) {baseCtors.forEach(baseCtor => {Object.getOwnPropertyNames(baseCtor.prototype).forEach(name => {derivedCtor.prototype[name] = baseCtor.prototype[name]})})
}
applyMixins()
?這個(gè)工具函數(shù)可以封裝在項(xiàng)目中一個(gè)核心函數(shù)庫(kù)中。
4. 小結(jié)
混入這種思想在一些開(kāi)源項(xiàng)目如?material
、vue-class-component
?中被廣泛使用,我們?nèi)粘9ぷ髦幸部梢愿鶕?jù)需求借鑒使用。