JS装饰器是ES7的新语法,浏览器,nodejs不一定支持,需要babel转译。
实验环境
创建一个目录test,结构为:
1 2 3 4 5 6 7
| . ├── .babelrc ├── .npmrc ├── lib ├── package.json └── src └── index.js
|
babel的装饰器配置:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| { "presets": [ "@babel/preset-env" ], "plugins": [ [ "@babel/plugin-proposal-decorators", { "legacy": true } ], "@babel/plugin-proposal-class-properties" ] }
|
依赖包与测试命令:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| { "name": "testmobx", "version": "1.0.0", "description": "testmobx", "main": "index.js", "directories": { "lib": "lib" }, "scripts": { "build": "babel src -d lib", "test": "node lib/index.js" }, "author": "jason", "license": "MIT", "devDependencies": { "@babel/core": "^7.15.5", "@babel/cli": "^7.15.0", "@babel/plugin-proposal-class-properties": "^7.14.5", "@babel/plugin-proposal-decorators": "^7.15.4", "@babel/preset-env": "^7.15.6" } }
|
npm源:
1 2
| registry=https://registry.npm.taobao.org
|
安装依赖包:
测试代码
源码都在 src/index.js 中。js装饰器可以装饰的对象:类、属性、方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
|
function readOnly(target, key, descriptor) { console.log('target:', target, typeof target); console.log('key:', key, typeof key); console.log('desc:', descriptor, typeof descriptor); if (typeof key === 'string') { if (typeof descriptor.value === 'function') { console.log('~~~ decorator of method'); return descriptor.value; } else { return { ...descriptor, writable: false } } } else { console.log('~~~ decorator of cls'); return target; } }
class Oatmeal { @readOnly viscosity = 20; constructor(flavor) { this.flavor = flavor; } }
var oatmeal = new Oatmeal('Brown Sugar Cinnamon');
console.log(oatmeal);
console.log('\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~');
@readOnly class A { constructor() { this.a = 111; } };
var a = new A(); console.log(a.a);
console.log('\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~');
class B { constructor() { this.b = 222; } @readOnly show() { console.log(this.b); } }
var b = new B(); b.show();
|
执行结果
其中initializer
与babel相关,当装饰器给属性装饰时,属性描述符对象中会有initializer,为函数,执行descriptor.initializer()
后将返回属性的值20。
参考:
https://segmentfault.com/a/1190000021593373