网站搜索

AngularJS 的作用域无法绑定到 TypeScript 类的 this,用于 controllerAs 语法


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

从以下 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 函数风格实现,它可以正常工作(见下方代码片段的前半部分)。然而,类的版本则不行。现在我可以将 $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>

答案#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";
  }
}

答案#2

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

你在 controllerAs 语法上弄错了。应该这样做:

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

当 Angular 看到 controller as 时,会运行 new。