我的Angular应用程序由以下层组成:
service()
用于计算和数据修改factory()
用作多个控制器的公共数据存储controllers()
我的控制器从工厂公开功能,而工厂则从服务中调用功能。在HTML中,我运行控制器功能并向用户显示输出:{{ controller.function() }}
。
我注意到,当加载页面时,以及每次后续模型更改时,controller.function()
都会运行两次。为什么会这样?如何避免不必要的调用?
请参阅working example - 打开浏览器JS控制台,点击Run
并观察console.log()
行已执行两次。
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"];
}])
<!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>
为什么每个模型更改都会多次运行此函数,如何确保它只运行一次?
我尝试将工厂函数输出分配给控制器变量(并在HTML中使用{{ controller.function }}
- 注意缺少括号),但是函数只运行一次。当模型改变时,它应该在新数据上运行。
StackOverflow上报告的类似问题都是指ng-route模块,我没有使用它。
答案 0 :(得分:4)
这是因为您在表达式中调用函数sample()
,如下所示:
{{ main.sample() }}
如果你使用这样的表达式,这个函数将被调用至少两次。
原因是因为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>