【问题标题】:Correct way of wrapping javascript class in AngularJS module and inject angular services在AngularJS模块中包装javascript类并注入角度服务的正确方法
【发布时间】:2014-10-24 09:31:54
【问题描述】:

在我正在开发的 AngularJS 模块中,我有一个 Canvas 类定义为:

angular.module("myModule", [])
.factory("Canvas", function() {return Canvas;});

var Canvas = function(element, options) {
    this.width = options.width || 300;
    this.height = options.height || 150;
    this.HTMLCanvas = $(element).get(0);
    this.HTMLCanvas.width = canvas.width;
    this.HTMLCanvas.height = canvas.height;
    this.objects = [];
    //Initialize canvas
    this.init();
}
Canvas.prototype.init = function() {/*...*/};
Canvas.prototype.otherMethod = function() {/*...*/};

现在,Canvas 类永远不会从模块内部实例化,而是从 AngularJS 控制器实例化,如下所示:

angular.module("myApp.controllers", ["myModule"])
.controller("MainCtrl", ["Canvas", function(Canvas) {
    var canvas = new Canvas("#canvas", {/*options object*/});
    //...
}]);

到目前为止,一切都像一个魅力。 但是后来我意识到我需要在我的画布对象中使用$q 服务,并且由于我不想诉诸将它注入我的控制器然后将其传递给Canvas 构造函数,所以我想修改我的模块,例如所以:

angular.module("myModule", [])
.factory("Canvas", ["$q", function(q) {
    var that = this;
    that.q = q;
    return function() {
        Canvas.apply(that, arguments);
    };
}]);

var Canvas = function(element, options) {
    console.log(this.q, element, options);
    this.width = options.width || 300;
    this.height = options.height || 150;
    this.HTMLCanvas = $(element).get(0);
    this.HTMLCanvas.width = canvas.width;
    this.HTMLCanvas.height = canvas.height;
    this.objects = [];
    //Initialize canvas
    this.init();
}
Canvas.prototype.init = function() {/*...*/};
Canvas.prototype.otherMethod = function() {/*...*/};

初始的console.log 正确记录了$q 服务和Canvas 的原始参数elementoptions,但在调用其init 方法时中断:

TypeError: undefined is not a function

我想这是因为 this 不再是 Canvas 的实例,而是匿名函数 function(q) {...} 的实例。
关于如何使用 q 属性实例化新的 Canvas 对象并仍然保留类的方法的任何提示?

编辑

我稍微修改了我的代码,以便更好地了解我想要实现的目标:

angular.module("myModule", [])
//.factory("Canvas", function() {return Canvas;})
//.factory("Canvas", ["$q", CanvasFactory])

function CanvasFactory(q) {
    var canvas = this;
    canvas.q = q;
    return function() {
        Canvas.apply(canvas, arguments);
    };
}

var Canvas = function(element, options) {
    console.log(this instanceof Canvas, typeof this.q !== "undefined");
};

如果我取消注释第一个工厂,console.log 产生 true false,而第二个工厂产生 false true。我的目标是获得true true,这意味着this 实际上是Canvas 类的一个实例并且 定义了q 属性。非常感谢任何提示。

【问题讨论】:

    标签: javascript angularjs angularjs-module


    【解决方案1】:

    我想通了:

    angular.module("myModule", [])
    .factory("Canvas", ["$q", function(q) {
        Canvas.prototype.q = q;
        return Canvas;
    }]);
    
    var Canvas = function(element, options) {
        console.log(this instanceof Canvas, typeof this.q !== "undefined");
    };
    

    此日志:true true

    【讨论】:

      【解决方案2】:

      我这样创建 Canvas 服务并且可以正常工作:

      var app = angular.module('myModule', []);
      
      app.factory("Canvas", ["$q", function($q) {
      
          var Canvas = function(element, options) {
              this.q = $q;
      
              this.init();
              console.log(this.q, element, options);
          }
          Canvas.prototype.init = function() {/*...*/};
          Canvas.prototype.otherMethod = function() {/*...*/};
      
          return Canvas;
      }]);
      
      app.controller('MainCtrl', ['$scope', 'Canvas', function($scope, Canvas) {
          console.log( new Canvas().q );  
      }]);
      

      你也可以在 Pluncer here看到这个

      【讨论】:

      • 谢谢,这是一种有效的方法,但它需要在工厂函数内部编写Canvas类,这在一定程度上限制了在其他地方重用它的可能性模块或将其分解为单独的文件。因此我投了赞成票,但我会接受我自己的答案,因为我同时想通了! :)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-11-17
      • 2013-10-29
      相关资源
      最近更新 更多