JavaScript

[ECMAScript] 配置和使用Decorator

2017-04-10  本文已影响836人  何幻

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

上一篇 下一篇

猜你喜欢

热点阅读