【问题标题】:ES2015 + ES2016 (decorators, comprehensions, ...) + Angular 1.x ComponentsES2015 + ES2016 (decorators, comprehensions, ...) + Angular 1.x Components
【发布时间】:2015-07-11 16:15:47
【问题描述】:

我正在开发一个使用 Angular 1.x 的 Web 应用程序架构,它仍然用于将事物粘合在一起。定义一个新组件相当容易:

class CustomComponent {
  constructor(dep1, dep2, dep3) {
    this.deps = { dep1, dep2, dep3 };
    /* app code */
  }

  /* link, compile, instance methods, template generators... */

  @readonly static $inject = ['dep1', 'dep2', 'dep3'];
}

我想做的是排除注入问题 - 换句话说,我不想每次都编写 this.depsstatic $inject 代码,而是让它自动生成 - 比如说,用一些东西就像 ES7 中的装饰器一样。然后代码将看起来像以下几行:

@injectionFromCtorComponents
class MyClass {
  constructor (dep1, dep2, dep3) {
    /* app logic */
  }
}

现在,静态部分是可行的,虽然很丑:

const angularInjectAnnotationFromCtor = (target) => {
    let regexStr = `^function ${target.name}\\\((.*)\\\)[.\\s\\S]*}$`;
    let regex = new RegExp(regexStr, 'gm');
    let ctorArgsStr = target.prototype.constructor.toString().replace(regex, '\$1');
    let ctorArgs = ctorArgsStr.replace(/ /g, '').split(',');

    target.$inject = ctorArgs;
};

但是,保存实例上的构造函数依赖项要复杂得多。我想出了以下内容,尽管它充其量是脆弱的:

const readonly = (target, key, descriptor) => Object.assign(descriptor, { writable: false });

class AngularComponent {
  constructor () {
    let ctorArgs = [...arguments];
    let argNames = ctorArgs.pop();

    // let's leave comprehensions out of this :)
    this.deps = 
      argNames.reduce((result, arg, idx) => Object.assign(result, ({ [arg]: ctorArgs[idx] })), {});
  }
}

@angularInjectAnnotationFromCtor
class MyClass extends AngularComponent {
    constructor (one, two, three) {
      super(one, two, three, MyClass.$inject);
    }
}

是的,这比我们开始的时候更糟糕......

那么问题来了,谁能提出一个更合理的解决方案?.. 还是我们应该坐下来期待在未来几年内的任何时候 Chrome 中的代理?

【问题讨论】:

    标签: javascript angularjs ecmascript-6 ecmascript-2016


    【解决方案1】:

    您想法的静态部分基本上就像根本没有$inject。没有意义。

    我建议忘记这个想法或将参数传递给装饰器:

    @inject('dep1', 'dep2', 'dep3')
    class MyClass {
      constructor (dep1, dep2, dep3) {
        /* app logic */
      }
    }
    

    构造器部分可以使用经典的装饰器模式来完成:

    function inject() {
      var dependencies = [...arguments];
    
      return function decorator(target) {
        target.$inject = dependencies;  
    
        return function() {
          this.deps = {};
          dependencies.forEach((dep, index) => {
            this.deps[dep] = arguments[index];
          });
    
          target.constructor.apply(arguments, this);
          return this;
        }
      }
    }
    

    【讨论】:

    • 非常好!不过,我不明白第一句话——为什么毫无意义?为什么喜欢根本没有?..
    • @IlyaAyzenshtok Angular 可以从构造函数本身获取依赖项。明确定义的$inject 的重点是拥有不会因缩小而丢失的字符串。所以基本上你正在尝试做 Angular 已经做的事情。
    • 重点是在没有特定框架的显式仪式的情况下创建缩小安全的代码。静态的 $inject 装饰器可以做到这一点——生成可以安全地缩小的代码,同时解决 Angular 问题。但除此之外,很好的答案,谢谢!我不知何故错过了类装饰器也可以返回一些东西的事实。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-10-20
    • 2016-03-29
    • 2017-06-30
    • 2019-10-29
    • 2015-02-11
    • 2019-02-01
    • 2016-09-11
    相关资源
    最近更新 更多