1. 目录结构
- dist
example.js
- example
index.html
index.js
+ node_modules
.babelrc
package.son
webpack.config.js
2. 环境配置
(1)配置工程依赖:./package.json
{
"name": "test-decorator",
"version": "1.0.0",
"dependencies": {},
"devDependencies": {
"babel-loader": "^6.2.10",
"babel-plugin-transform-decorators-legacy": "^1.3.4",
"babel-preset-stage-0": "^6.24.1",
"webpack": "^1.13.1"
}
}
(2)配置Babel:./babelrc
{
"presets": [
"es2015",
"stage-0"
],
"plugins": [
"transform-decorators-legacy"
]
}
(3)配置Webpack:./webpack.config.js
module.exports = {
entry: {
example: './example/index.js'
},
output: {
path: './dist/',
filename: '[name].js',
libraryTarget: 'umd'
},
module: {
loaders: [{
test: /.js$/,
loader: 'babel-loader'
}]
}
};
3. 用例
const D1 = Class => {
//Class没有v0这个属性
console.log(Class.v0); //undefined
Class.v0 = 1;
return Class;
};
const D2 = Class => {
//可以获取静态属性
console.log(Class.v1); //0
Class.v1 = 2;
return Class;
}
const D3 = Class => {
const f1 = Class.f1;
//可以获取静态属性,属性为箭头函数
console.log(f1); //x => x+1
Class.f1 = z => f1(z) + 1;
return Class;
}
const D4 = instance => {
//当实例为public class field时,无法获取实例属性
console.log(instance.v2); //undefined
instance.v2 = 4;
return instance;
}
const D5 = instance => {
//当实例为public class field时,无法获取实例属性
console.log(instance.f2); //undefined
instance.f2 = z => z + 4;
return instance;
};
const D6 = instance => {
const f3 = instance.f3;
//实例方法,可以获取
console.log(f3); //x => x+1
instance.f3 = z => f3(z) + 4;
return instance;
};
@D1
class A {
@D2
static v1 = 0; //static public class field
@D3
static f1 = x => x + 1; //static public class field
@D4
v2 = 0; //public class field
@D5
f2 = x => x + 1; //public class field
//You can't attach decorators to a class constructor
constructor() { }
@D6
f3(x) { //mothod
return x + 1;
}
};
console.warn(A.v0); //1
console.warn(A.v1); //2
console.warn(A.f1(1)); //3
const a = new A;
console.warn(a.v2); //4
console.warn(a.f2(1)); //5
console.warn(a.f3(1)); //6
注意事项:
(1)constructor
不能添加decorator
(2)decorator是一个函数。
如果添加在类上或者类的静态字段上,参数为这个类,返回值将替换原来的类。
const f = Class => class B { };
@f
class A{
}
console.log(A); //B
如果添加在实例字段或者方法上,参数为实例,返回值必须是一个对象,且该对象将被丢弃。
const f = x => {
const fn = x.fn;
x.fn = () => fn() + 1;
return {
v: 2
};
};
class A {
@f
fn() {
return 1;
}
gn() {
console.log(this.fn()); //2
//this还是原来的实例,而不是{v:2}
console.log(this.v); //undefined
}
}
const a = new A;
a.gn();
(3)decorator修饰public class field时,如果该field是一个实例字段,则通过decorator的参数(参数是当前类的实例)无法获取该字段。
(可能是Babel的问题
(4)不在类中的普通函数,不支持decorator。
const f = x => x;
// Leading decorators must be attached to a class declaration
@f
function g() {
}
console.log(g);
参考
Class and Property Decorators
babel-plugin-transform-decorators-legacy