ES7-Decorator
装饰器常见用法
react-redux 中的 connect
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { increment, decrement } from '../redux/actions'
@connect(
state=>({value: state.test}),
{increment,decrement}
)
class Counter extends Component {
onIncrease() {
this.props.increment(5);
}
onDecrement() {
this.props.decrement(3);
}
render() {
const { value } = this.props;
return (
<div>
Test: 测试{value}
<button onClick={this.onIncrease.bind(this)}>增加</button>
<button onClick={this.onDecrement.bind(this)}>减少</button>
</div>
);
}
}
export default Counter;
Ant Design 的Form.create
import React, { Component } from 'react';
import { Form } from 'antd';
@Form.create({
name: 'ingestion_form'
})
class IngestionForm extends Component {
// 表单组件
}
ES7-Decoratro
❝仅仅包装现有的模块,使之 “更加华丽” ,并不会影响原有接口的功能 —— 好比你给手机添加一个外壳罢了,并不影响手机原有的通话、充电等功能;
❞
这是网上看到比较形象的比喻,钢铁侠本质是人,但通过外穿的装备获得增强的能力
装饰器是实现「面向切面的编程(AOP)编程」的一种方式,他可以让我们的程序设计更优雅
它具体做了什么工作 ?它“装饰”了类、方法、访问器、属性和参数——“它”是指类装饰器、方法装饰器、访问器装饰器、属性装饰器和参数装饰器
类的装饰(Class decorators)
@testable
class MyTestableClass {
// ...
}
function testable(target) {
target.isTestable = true;
}
MyTestableClass.isTestable // true
// 相当于定义
class MyTestableClass {
static isTestable = true
}
@testable就是一个装饰器。它修改了MyTestableClass这个类的行为,为它加上了静态属性isTestable。testable函数的参数target是MyTestableClass类本身
基本上,装饰器的行为就是下面这样
@decorator
class A {}
// 等同于
class A {}
A = decorator(A) || A;
扩展参数,可以在装饰器外面在加一层函数(闭包)
function testable(isTestable) {
return function(target) {
target.isTestable = isTestable;
}
}
@testable(true)
class MyTestableClass {}
MyTestableClass.isTestable // true
@testable(false)
class MyClass {}
MyClass.isTestable // false
上面的例子都是添加类型的静态属性,如果想添加实例属性,可以通过target.prototype.value来添加。
方法/属性的装饰(Class property decorators)
看下 ES6 中的类
class Cat {
say() {
console.log("meow ~");
}
}
上面的其实只是个语法糖,实际添加类属性时候,会使用Object.defineProperty这个方法,它接受 3 个参数target、name、descriptor
function Cat() {}
Object.defineProperty(Cat.prototype, "say", {
value: function() { console.log("meow ~"); },
enumerable: false,
configurable: true,
writable: true
});
「属性/方法装饰器的参数和上面Object.defineProperty使用的参数相同」
比如有的时候,我们希望把我们的部分属性置成只读,以避免别人对其进行修改,如果使用装饰器的话,我们可以这样来做:
function readonly(target, name, descriptor) {
discriptor.writable = false;
return discriptor;
}
class Cat {
@readonly
say() {
console.log("meow ~");
}
}
var kitty = new Cat();
kitty.say = function() {
console.log("woof !");
}
kitty.say() // meow ~
class Math {
@log
add(a, b) {
return a + b;
}
}
function log(target, name, descriptor) {
var oldValue = descriptor.value;
descriptor.value = function() {
console.log(`Calling ${name} with`, arguments);
return oldValue.apply(this, arguments);
};
return descriptor;
}
const math = new Math();
// passed parameters should get logged now
math.add(2, 4);
JS 里对于装饰器的描述
❝A decorator is:
❞
- an expression
- that evaluates to a function
- that takes the target, name, and decorator descriptor as arguments
- and optionally returns a decorator descriptor to install on the target object
babel --plugins transform-decorators-legacy es6.js > es5.js
参考文档: