AngularJS指令工厂只调用一次

时间:2015-10-15 08:29:38

标签: angularjs google-closure-compiler google-closure

我们目前正在迁移到Google Closure Compiler。我们重构了旧的代码库,因此它符合本文:A radical new approach to developing AngularJS apps

指令应如下所示:

/**
 * @constructor
 */
var Directive = function(version) {
  this.version = version;
  this.link = this.link.bind(this);

  this.scope;
  this.elem;
  this.attrs;
};

/**
 * Version directive factory. Entry point and used in `module.directive`.
 */
Directive.factory = function(version) {
  var dir = new Directive(version);
  return {
    link: dir.link
  };
};

/**
 * Linking function.
 */
Directive.prototype.link = function(scope, elem, attrs) {
  this.scope = scope;
  this.elem = elem;
  this.attrs = attrs;
  this.elem.text(this.version.get());
};

angular.module('app', [])
  .directive('version', Directive.factory);

一切正常,直到我们在网站上多次使用指令。 Directive.factory只会被调用一次。因此,站点上的所有指令共享相同的Directive对象。我们不明白,为什么会这样。

2 个答案:

答案 0 :(得分:2)

An Angular service is a singleton object created by a service factory。所以DDO个对象是,它们是单个数组,它们是由directive factory functions返回的对象创建的(指令似乎是引擎盖下的服务)。一旦调用了工厂函数(在您的情况下为Directive.factory),其结果将缓存为versionDirective服务实例。

一旦你知道Angular treats compile and link functions究竟是如何完成的,就可以通过这样的伎俩:

Directive.factory = function(version) {
  return {
    compile: function () {
      var dir = new Directive(version);
      // by default there is no 'this' in link
      return angular.bind(dir, dir.link);
    }
  };
};

除非你知道你做得很好,否则我会反对它。它不会有助于测试性,可维护性,或任何会滥用框架的东西。

“彻底的新方法”可能会或可能不会有益,但它肯定不会暗示这样的事情。

答案 1 :(得分:1)

我改变了你的例子,以反映指令构造函数是一个共享的单例。

/**
 * @constructor
 */
var Directive = function(version) {
  this.version = version;
};

/**
 * Version directive factory. Entry point and used in `module.directive`.
 */
Directive.factory = function(version) {
  return new Directive(version);
};

/**
 * Linking function.
 */
Directive.prototype.link = function(scope, elem, attrs) {
  // this refers to the Directive singleton - it's shared between
  // multiple invocations.
  elem.text(this.version.get());
};

angular.module('app', [])
  .directive('version', Directive.factory);

如果您想要最初的目标,可以改变链接方法来构建对象:

/**
 * Linking function.
 */
Directive.prototype.link = function(scope, elem, attrs) {
  // This will be created everytime the template is cloned
  var versionDirective = new VersionDirectiveLink(scope, elem, attrs);
  versionDirective.setText(this.version.get());
};

后一种变体每次克隆模板时都会创建一个对象。您可以通过这种方式支持构造函数的更高级行为。