【问题标题】:AngularJS scope not binding to this of TypeScript class for controllerAs syntaxAngularJS 范围未绑定到 ControllerAs 语法的 TypeScript 类的 this
【发布时间】:2015-04-02 23:57:12
【问题描述】:

我正在试用 AngularJS,并且正在尝试使用 TypeScript 类为大型项目做好准备。我遇到的问题是控制器类的this 没有绑定到ng-controller 指令所在的DOM 部分内的范围。

从以下 TypeScript 代码开始:

angular.module('testApp')
.controller('TypeScriptController', () => new TypeScriptController())

// Controller implementation via TypeScript
class TypeScriptController {
  text = "Please click the button";

  constructor() {}

  buttonClick () {
    this.text = "The button was clicked";
  }
}

并使用

将控制器绑定到 DOM
<main ng-controller="TypeScriptController as TSCtrl">

如果我使用标准的 ES5 函数样式来实现它,它可以正常工作(参见下面的代码 sn-p 的前半部分)。但是类版本没有。现在我可以将$scope 变量传递给控制器​​并将$scope 的属性绑定到this 但随后HTML 中的controllerAs 语法将被忽略。但是,我想避免将$scope 传递给每个控制器。

我知道 AngularJS 1.3 为指令引入了 bindToController 选项,但我不知道如何在这种情况下应用它。

示例:

在这个例子中展示了控制器的 ES5 和 TypeScript 实现。控制器只包含一个方法,ng-click 调用该方法在按钮下方写入文本。 ES5 版本有效。 TypeScript 版本没有。我也在Plunker

中实现了这一点

angular.module('testApp', [])
  .controller('MainController', MainController);

function MainController() {
  this.text = "Please click the button";
  this.buttonClick = function() {
    this.text = "The button was clicked";
  };
};

// Compiled from TypeScript source
angular.module('testApp').controller('TypeScriptController', function() {
  return new TypeScriptController();
});
// Controller implementation via TypeScript
var TypeScriptController = (function() {
  function TypeScriptController() {
    this.text = "Please click the button";
  }
  TypeScriptController.prototype.buttonClick = function() {
    this.text = "The button was clicked";
  };
  return TypeScriptController;
})();
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>

<body ng-app="testApp">
  <main ng-controller="MainController as mainCtrl">
    <h1>Hello World!</h1>
    <p>
      <input type="button" name="testInput" value="Test button" ng-click="mainCtrl.buttonClick()">
    </p>
    <p>{{mainCtrl.text}}</p>
  </main>
  <main ng-controller="TypeScriptController as TSCtrl">
    <h1>Hello TypeScript!</h1>
    <p>
      <input type="button" name="testInput" value="Test button" ng-click="TSCtrl.buttonClick()">
    </p>
    <p>{{TSCtrl.text}}</p>
  </main>
</body>

【问题讨论】:

    标签: angularjs typescript


    【解决方案1】:

    如果您希望 buttonClick 成为实例成员(就像您在 ES5 版本中所做的那样)而不是原型成员,请使用箭头函数:

    // Controller implementation via TypeScript
    class TypeScriptController {
      text = "Please click the button";
    
      constructor() {}
    
      // Arrow function captures 'this'
      buttonClick = () => {
        this.text = "The button was clicked";
      }
    }
    

    【讨论】:

    • 感谢 Ryan,但也没有看到 text 变量。
    【解决方案2】:

    angular.module('testApp') .controller('TypeScriptController', () => new TypeScriptController())

    controllerAs 语法有这个错误。而是这样做:

    angular.module('testApp')
    .controller('TypeScriptController', TypeScriptController)
    

    当 Angular 将控制器视为时,它将运行 new

    【讨论】:

    • 感谢您的提示。为此,需要在类定义之后将控制器传递给 angular。这是因为TypeScriptController 类被定义为函数分配给的变量。因此TypeScriptController 函数在类定义之后才可用。对我来说,这将使通过控制器的代码更难找到(在文件末尾),但它可以工作。
    • 我写了my own answer 结合了你的笔记和我自己的实现。
    【解决方案3】:

    @basarat 所述,TypeScriptController 应直接传递给控制器​​。

    angular.module('testApp')
    .controller('TypeScriptController', TypeScriptController)
    

    第二个问题是类定义需要在TypeScriptController 传递给角度.controller() 函数之前发生。这是因为 TypeScript 将类编译为包含函数的变量。

    // Compiled from TypeScript source
    // Note the variable definition
    var TypeScriptController = (function() {
      function TypeScriptController() {
        this.text = "Please click the button";
      }
      TypeScriptController.prototype.buttonClick = function() {
        this.text = "The button was clicked";
      };
      return TypeScriptController;
    })();
    

    在传递给 angular 之前需要计算这个变量。这不同于典型的 JavaScript 函数定义,因为 JavaScript hoisting 而在程序开始时可用。

    // MainController function is already defined
    angular.module('testApp', [])
    .controller('MainController', MainController);
    
    // Available above because defined as "function FuncName()"
    function MainController() {
      this.text = "Please click the button";
      this.buttonClick = function() {
        this.text = "The button was clicked";
      };
    }
    

    因此解决方法是在传递控制器函数之前定义 TypeScript 类。

    // Controller implementation via TypeScript
    class TypeScriptController {
      text = "Please click the button";
    
      constructor() {}
    
      buttonClick() {
        this.text = "The button was clicked";
      }
    }
    // Now that class is defined we can pass the controller directly
    angular.module('testApp')
    .controller('TypeScriptController', TypeScriptController)
    

    【讨论】:

      猜你喜欢
      • 2018-12-18
      • 2016-06-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-09-09
      • 2023-04-09
      • 1970-01-01
      • 2014-08-16
      相关资源
      最近更新 更多