ES6学习笔记(二十) - Decorator修饰器

导语:(Decorator)修饰器的使用,有些类似对某些类或者方法,提前执行一些操作。

链接:http://es6.ruanyifeng.com/#docs/decorator



Decorator 修饰器

1、类的修饰


修饰器(Decorator)是一个函数,用来修改类的行为。这是ES7的一个提案,目前Babel转码器已经支持。

修饰器对类的行为的改变,是代码编译时发生的,而不是在运行时。这意味着,修饰器能在编译阶段运行代码。

function testable(target) {
  target.isTestable = true;
}
@testable
class MyTestableClass {}
console.log(MyTestableClass.isTestable) // true


2、方法的修饰


修饰器不仅可以修饰类,还可以修饰类的属性。

class Person {
  @readonly
  name() { return `${this.first} ${this.last}` }
}

@log修饰器,可以起到输出日志的作用。@log修饰器的作用就是在执行原始的操作之前,执行一次console.log,从而达到输出日志的目的。

修饰器有注释的作用。

@testable
class Person {
  @readonly
  @nonenumerable
  name() { return `${this.first} ${this.last}` }
}

如果同一个方法有多个修饰器,会像剥洋葱一样,先从外到内进入,然后由内向外执行。


3、修饰器不能用于函数

修饰器只能用于类和类的方法,不能用于函数,因为存在函数提升。


4、Core-decorators.js

core-decorators.js是一个第三方模块,提供了几个常见的修饰器,通过它可以更好地理解修饰器。

(1)@autobind

autobind修饰器使得方法中的this对象,绑定原始对象。

(2)@readonly

readonly修饰器使得属性或方法不可写。

(3)@override

override修饰器检查子类的方法,是否正确覆盖了父类的同名方法,如果不正确会报错。

(4)@deprecate (别名@deprecated)

deprecate或deprecated修饰器在控制台显示一条警告,表示该方法将废除。

(5)@suppressWarnings

suppressWarnings修饰器抑制decorated修饰器导致的console.warn()调用。但是,异步代码发出的调用除外。


5、使用修饰器实现自动发布


我们可以使用修饰器,使得对象的方法被调用时,自动发出一个事件。

它的用法如下。

import publish from "path/to/decorators/publish";
class FooComponent {
  @publish("foo.some.message", "component")
  someMethod() {
    return {
      my: "data"
    };
  }
  @publish("foo.some.other")
  anotherMethod() {
    // ...
  }
}

以后,只要调用someMethod或者anotherMethod,就会自动发出一个事件。

let foo = new FooComponent();
foo.someMethod() // 在"component"频道发布"foo.some.message"事件,附带的数据是{ my: "data" }
foo.anotherMethod() // 在"/"频道发布"foo.some.other"事件,不附带数据


6、Mixin


在修饰器的基础上,可以实现Mixin模式。所谓Mixin模式,就是对象继承的一种替代方案,中文译为“混入”(mix in),意为在一个对象之中混入另外一个对象的方法。

我们部署一个通用脚本mixins.js,将mixin写成一个修饰器。

export function mixins(...list) {
  return function (target) {
    Object.assign(target.prototype, ...list);
  };
}

然后,就可以使用上面这个修饰器,为类“混入”各种方法。

import { mixins } from './mixins';
const Foo = {
  foo() { console.log('foo') }
};
@mixins(Foo)
class MyClass {}
let obj = new MyClass();
obj.foo() // "foo"


7、Trait


Trait也是一种修饰器,效果与Mixin类似,但是提供更多功能,比如防止同名方法的冲突、排除混入某些方法、为混入的方法起别名等等。

下面采用traits-decorator这个第三方模块作为例子。这个模块提供的traits修饰器,不仅可以接受对象,还可以接受ES6类作为参数。

import { traits } from 'traits-decorator';
class TFoo {
  foo() { console.log('foo') }
}
const TBar = {
  bar() { console.log('bar') }
};
@traits(TFoo, TBar)
class MyClass { }
let obj = new MyClass();
obj.foo() // foo
obj.bar() // bar

Trait不允许“混入”同名方法。

import { traits } from 'traits-decorator';
class TFoo {
  foo() { console.log('foo') }
}
const TBar = {
  bar() { console.log('bar') },
  foo() { console.log('foo') }
};
@traits(TFoo, TBar)
class MyClass { }
// 报错
// throw new Error('Method named: ' + methodName + ' is defined twice.');
//        ^
// Error: Method named: foo is defined twice.


8、Babel转码器的支持


Babel转码器已经支持Decorator。

首先,安装babel-core和babel-plugin-transform-decorators。由于后者包括在babel-preset-stage-0之中,所以改为安装babel-preset-stage-0亦可。

$ npm install babel-core babel-plugin-transform-decorators

然后,设置配置文件.babelrc。

{
  "plugins": ["transform-decorators"]
}

这时,Babel就可以对Decorator转码了。


 赞(0
成功
相关阅读: