添加自定义类装饰器

时间:2017-08-04 07:43:15

标签: angular angular-decorator

根据这个tutorial我尝试实现自定义装饰器,允许我们根据用户角色限制对组件类的访问。否则重定向到其他组件(我知道它有其他策略来存档,但它不适合我们的用例)。

它可以作为我的方面,,但仅当我在本地计算机上运行而不是在部署服务器时。错误就像它不能在每个组件的构造函数中注入任何服务或类使用这个装饰器???

角色required.decorator.ts

export function RoleRequired(roles: string[], redirectUrl = '/forbidden') {

    return function<T extends {new(...args:any[]):{}}> (constructor:T) {

        // save a reference to the original constructor
        const original = constructor;

        // a utility function to generate instances of a class
        function construct(constructor, args) {
            const c : any = function () {
                return constructor.apply(this, args);
            };
            c.prototype = constructor.prototype;
            return new c();
        }

        // the new constructor behaviour
        const f : any = function(router: Router, ...args) {
            console.log("Class: " + original.name);
            this.__verifyRole = JSON.parse(localStorage.getItem("roles")) || [];

            const that = this;
            const isGrant = roles.every((item, index) => {
                return that.__verifyRole.indexOf(item) != -1
            });

            if (!isGrant) {
                router.navigate([redirectUrl]);
            }

            return construct(original, args);
        };

        // copy prototype so intanceof operator still works
        f.prototype = original.prototype;

        // copy metadata to new constructor
        let metadatakeys = Reflect.getMetadataKeys(constructor);
        metadatakeys.forEach(function (key) {
            Reflect.defineMetadata(key, Reflect.getOwnMetadata(key, constructor), f)
        });

        // read dependencies list from 'cls', add our own dependency, and write list to 'newCls'
        let dependencies = Reflect.getOwnMetadata('design:paramtypes', constructor);
        dependencies = [Router].concat(dependencies);
        Reflect.defineMetadata('design:paramtypes', dependencies, f);

        // return new constructor (will override original)
        return f;
    }
}

PREREQUISITE

app.module.ts导入此课程 导入&#39;反映元数据&#39;;

USAGE

@RoleRequired(['role.user.chat'])
export class ChatRoomComponent {}

错误消息是启动组件时注入类的所有属性。

  

ERROR TypeError:无法读取属性&#39; informSoundSettingChange&#39;的   未定义

的package.json

{
  "name": "alpha-love-chat-ng",
  "version": "1.0.0",
  "license": "MIT",
  "angular-cli": {},
  "scripts": {
    "ng": "ng",
    "start": "ng serve --deploy / --proxy-config proxy.conf.json",
    "build": "ng build --prod --aot output-hashing none --deploy /",
    "test": "ng test",
    "lint": "ng lint",
    "e2e": "ng e2e"
  },
  "private": true,
  "dependencies": {
    "@angular/animations": "^4.2.6",
    "@angular/cdk": "^2.0.0-beta.8",
    "@angular/common": "^4.2.6",
    "@angular/compiler": "^4.2.6",
    "@angular/core": "^4.2.6",
    "@angular/forms": "^4.2.6",
    "@angular/http": "^4.2.6",
    "@angular/material": "^2.0.0-beta.8",
    "@angular/platform-browser": "^4.2.6",
    "@angular/platform-browser-dynamic": "^4.2.6",
    "@angular/router": "^4.2.6",
    "angular-datatables": "^4.1.1",
    "angular2-notifications": "^0.7.4",
    "angular2-uuid": "^1.1.1",
    "bootstrap": "^3.3.7",
    "core-js": "^2.4.1",
    "datatables.net": "^1.10.15",
    "datatables.net-dt": "^1.10.15",
    "howler": "^2.0.4",
    "jquery": "^3.2.1",
    "lz-string": "^1.4.4",
    "malihu-custom-scrollbar-plugin": "^3.1.5",
    "moment": "^2.18.1",
    "moment-timezone": "^0.5.13",
    "ng2-modal": "0.0.25",
    "ngx-facebook": "^2.4.0",
    "ngx-infinite-scroll": "^0.5.1",
    "reflect-metadata": "^0.1.10",
    "rxjs": "^5.4.2",
    "rxjs-extra": "^0.1.1",
    "signalr": "^2.2.2",
    "underscore": "^1.8.3",
    "zone.js": "^0.8.4"
  },
  "devDependencies": {
    "@angular/cli": "^1.2.0",
    "@angular/compiler-cli": "^4.2.6",
    "@angular/language-service": "^4.2.6",
    "@types/bootstrap": "^3.3.34",
    "@types/datatables.net": "^1.10.4",
    "@types/howler": "^2.0.2",
    "@types/jasmine": "2.5.45",
    "@types/jquery": "^3.2.6",
    "@types/lz-string": "^1.3.32",
    "@types/moment": "^2.13.0",
    "@types/moment-timezone": "^0.2.34",
    "@types/node": "^6.0.80",
    "codelyzer": "~3.0.1",
    "jasmine-core": "~2.6.2",
    "jasmine-spec-reporter": "~4.1.0",
    "karma": "~1.7.0",
    "karma-chrome-launcher": "~2.1.1",
    "karma-cli": "~1.0.1",
    "karma-coverage-istanbul-reporter": "^1.2.1",
    "karma-jasmine": "~1.1.0",
    "karma-jasmine-html-reporter": "^0.2.2",
    "protractor": "~5.1.2",
    "ts-node": "~3.0.4",
    "tslint": "~5.3.2",
    "typescript": "~2.3.3"
  }
}

1 个答案:

答案 0 :(得分:0)

根据@ n00dl3在评论中建议..

  

说真的,我担心这是一个AOT限制......我猜它会创造出来   在构建时注入逻辑,因此您无法在AOT中使用装饰器   启用..

但是,我尝试一开始并不工作,因为......

  

&#34; ng build --prod --aot output-hashing none --deploy /&#34;

我只是删除了--aot,但我仍然留下了这个标记--prod,默认情况下它会启用--aot true所以我按--aot false github.com/angular/angular-cli/wiki/build <修复/ p>

最终版

  

&#34; ng build --prod --aot false output-hashing none --deploy /&#34;

而不是

  

&#34; ng build --prod output-hashing none --deploy /&#34;

总之,删除--aot标志已解决,我的问题阻止它删除我的自定义装饰器。