为什么Angular为每个模型更改运行控制器功能两次?

Mir*_*osz 12 javascript angularjs

我有以下层的Angular应用程序:

  • service() 用于计算和数据修改
  • factory() 用作多个控制器的通用数据存储
  • 少数 controllers()

我的控制器从工厂公开功能,反过来从服务调用功能.在HTML中,我运行控制器功能并向用户显示输出:{{ controller.function() }}.

我注意到,当加载页面时,以及每次后续模型更改时,controller.function()都会运行两次.为什么会这样?如何避免不必要的调用?

查看工作示例 - 打开浏览器JS控制台,单击Run并观察该console.log()行执行两次.


JavaScript的

angular.module('myApp',[])
.service('Worker', [function() {
    this.i = 0;
    this.sample = function(data) {
    console.log(this.i.toString() + " " + Math.random().toString());
    return JSON.stringify(data);
  };
}])
.factory('DataStorage', ['Worker', function(worker) {
    var self = this;
    self.data = [{}, {}];
    self.getData = function() {
      return self.data;
    }
  self.sample = function() {
    return worker.sample(self.data);
  };
  return {
    getData: self.getData,
    sample: self.sample
  };
}])
.controller('MainController', ['DataStorage', function(DataStorage) {
    var self = this;
    self.data = DataStorage.getData();
  self.sample = DataStorage.sample;
}])
.controller('DataSource', [function() {
  var self = this;
  self.data = ["one", "two", "three", "four", "five", "six"];
}])
Run Code Online (Sandbox Code Playgroud)

HTML

<!DOCTYPE html>
<html ng-app="myApp">

  <head>
    <script data-require="angularjs@1.5.8" data-semver="1.5.8" src="https://opensource.keycdn.com/angularjs/1.5.8/angular.min.js"></script>
    <script src="script.js"></script>
  </head>

  <body ng-controller="MainController as main">
    <div ng-controller="DataSource as datasource">
      <div ng-repeat="select in main.data">
        <select ng-model="select.choice" ng-options="value for value in datasource.data">
          <option value="">-- Your choice --</option>
        </select>
      </div>

    <pre>
      {{ main.sample() }}
    </pre>
  </div>
  </body>

</html>
Run Code Online (Sandbox Code Playgroud)

为什么每个模型更改都会运行多次此函数,如何确保它只运行一次?

我已经尝试将工厂函数输出分配给控制器变量(并{{ controller.function }}在HTML中使用- 注意缺少括号),但是函数只运行一次.当模型更改时,它应该在新数据上运行.

在StackOverflow上报告的类似问题都涉及ng-route模块,我没有使用它.

kat*_*330 4

发生这种情况是因为您在表达式中调用函数,sample()如下所示:

{{ main.sample() }}
Run Code Online (Sandbox Code Playgroud)

如果您使用这样的表达式,该函数将至少被调用两次。

原因是因为 Angular 会运行摘要循环,直到所有内容都是最新的(因此,至少会两次)。在您的情况下,它第一次运行以返回值,第二次运行以验证是否还有任何更改。

如果您将函数放在指令中,则可以确保它只运行一次ng-change

在你的情况下它将是:

 <select ng-model="select.choice" ng-change="main.sample()" ng-options="value for value in datasource.data">
      <option value="">-- Your choice --</option>
 </select>
Run Code Online (Sandbox Code Playgroud)