什么是 Mixin
为对象引入附加的方法或属性,从而达到修改对象结构的目的,即为 mixin.
function applyMixins(derivedCtor: any, baseCtors: any[]) {
baseCtors.forEach(baseCtor => {
Object.getOwnPropertyNames(baseCtor.prototype).forEach(name => {
derivedCtor.prototype[name] = baseCtor.prototype[name];
})
});
}
在Typescipt 之前,很多框架都提供了 Mixin 这个概念,我自己在 Extjs 和 早期的 React 中就学习过混入。
以下代码是 Mixin 在 React 中的使用方法,通过配置,组件可以像调用自己的方法一样调用外部对象的方法。
注: Mixin 在React 16 中已经被废弃了。 废弃的原因在文章的最后会提及。
var myMixin = {
mixinMethod: function() {
...
};
var createReactClass = require('create-react-class');
var TickTock = createReactClass({
mixins: [myMixin], // 使用 mixin
componentDidMount: function() {
this.mixinMethod(); // 调用 mixin 上的方法
},
render: function() {
return ...
}
});
ReactDOM.render(
<TickTock />,
document.getElementById('example')
);
Mixin 解决的问题
Mixin 解决的是横切关注点的问题(cross-cutting concern).
横切是 **AOP(Aspect-Oriented Programming,面向切片编程)**中的一个概念。
软件系统,可看作由一组关注点组成。其中,直接的业务关注点,是直切关注点。而为直切关注点提供服务的,就是横切关注点。通常,事务、日志、安全性等关注就是应用中的横切关注功能。
实现AOP的技术,主要分为两大类:一是采用动态代理技术,利用截取消息的方式,对该消息进行装饰,以取代原有对象行为的执行;二是采用静态横切,即通过重新包装对象,引入对应的 “切面”,即 mixin.
Typescript 中的 mixin
- Typescript 中并没有特殊的和 mixin 有关的语法糖
- 利用 Typescript 中implements 对类的多继承性来实现 mixin
class Shape {
draw(): void {
console.log("shape is drawing");
}
}
class Component {
display(): void {
console.log("component is displaying");
}
}
class Rectangle implements Shape, Component {
w: number;
h: number;
constructor(w: any, h: any) {
this.w = w;
this.h = h;
}
area(): number {
return this.w * this.h;
}
//just provide the empty implementation which will be replaced by the mixins helper function
//same as display: () => void
display(): void {
}
//same as draw: () => void
draw(): void {
}
}
function applyMixins(derivedCtor: any, baseCtors: any[]) {
baseCtors.forEach(baseCtor => {
Object.getOwnPropertyNames(baseCtor.prototype).forEach(name => {
derivedCtor.prototype[name] = baseCtor.prototype[name];
})
});
}
applyMixins(Rectangle, [Shape, Component]);
let rectangle: Rectangle = new Rectangle(4, 3);
rectangle.draw();
rectangle.display();
let area = rectangle.area();
console.log(area);
注意:Rectangle 中的空方法签名 draw 和 display 是必须的,如果缺失编译会报错
mixin 的缺点
大致聊一聊 mixin 的缺点以及为何 React 会放弃它: Mixins Considered Harmful
- mixin 导致的隐式依赖 (Mixins introduce implicit dependencies)
- mixin 导致命名冲突 (Mixins cause name clashes)
- mixin 滥用可能会导致代码复杂度直线上升。