两次对抗AngularJS执行控制器

Gre*_*reg 529 angularjs

我理解AngularJS会运行一些代码两次,有时甚至更多,比如$watch事件,不断检查模型状态等.

不过我的代码:

function MyController($scope, User, local) {

var $scope.User = local.get(); // Get locally save user data

User.get({ id: $scope.User._id.$oid }, function(user) {
  $scope.User = new User(user);
  local.save($scope.User);
});

//...
Run Code Online (Sandbox Code Playgroud)

执行两次,将2条记录插入我的数据库.我显然还在学习,因为我多年来一直在抨击这个!

Gre*_*reg 1045

应用程序路由器指定导航MyController如下:

$routeProvider.when('/',
                   { templateUrl: 'pages/home.html',
                     controller: MyController });
Run Code Online (Sandbox Code Playgroud)

但我也有这个home.html:

<div data-ng-controller="MyController">
Run Code Online (Sandbox Code Playgroud)

这消化了控制器两次.data-ng-controller从HTML中删除属性解决了问题.或者,该controller:属性可能已从路由指令中删除.

使用选项卡式导航时也会出现此问题.例如,app.js可能包含:

  .state('tab.reports', {
    url: '/reports',
    views: {
      'tab-reports': {
        templateUrl: 'templates/tab-reports.html',
        controller: 'ReportsCtrl'
      }
    }
  })
Run Code Online (Sandbox Code Playgroud)

相应的报告选项卡HTML可能类似于:

<ion-view view-title="Reports">
  <ion-content ng-controller="ReportsCtrl">
Run Code Online (Sandbox Code Playgroud)

这也将导致控制器运行两次.

  • 在ngController的文档中有一个很好的解释,http://docs.angularjs.org/api/ng/directive/ngController (5认同)
  • 这似乎是离开这个的最好的地方,经过几个小时的梳理我的代码后,不要问我怎么做,但当我把`<div ng-view> ...`更改为`<div class ="ng-view"时> ......,这个问题对我不利了.我之前没有遇到过这种行为,但也许其他人也有这种行为. (4认同)
  • @Josh将其保留在HTML中会降低灵活性。您将模板直接绑定到一个控制器。您可以将ctrl用作路由的语法。 (2认同)

shx*_*fee 127

AngularJS docs - ngController
请注意,您还可以通过$ route服务在路由定义中声明控制器,从而将控制器附加到DOM.常见的错误是在模板本身中使用ng-controller再次声明控制器.这将导致控制器连接并执行两次.

将ngRoute与ng-view指令一起使用时,控制器默认附加到该dom元素(如果使用ui-router,则为ui-view).因此,您无需再次在模板中附加它.

  • 我觉得令人困惑的是,作者把它作为旁注,而这显然是正确的方法.文档的引用清楚地回答了这个问题.我相信很多人会发现该文档的链接很有帮助. (4认同)

Jes*_*ing 69

我刚刚完成了这个,但问题与接受的答案不同.我真的把这个留给了我未来的自我,包括我修复它的步骤.

  1. 删除冗余控制器声明
  2. 检查路由中的尾部斜杠
  3. 检查 ng-ifs
  4. 检查是否有任何不必要的包装ng-view调用(我意外地留下了包含ng-view我的实际内容ng-view.这导致三次调用我的控制器.)
  5. 如果您使用的是Rails,则应turbolinksapplication.js文件中删除gem .我浪费了一整天才发现这一点.在这里找到答案.
  6. 使用ng-app和bootstrap初始化应用程序两次.两次对抗AngularJS执行控制器
  7. 当在指令的'link'-function中使用$ compile时,整个元素也有自己的控制器定义,并通过ng-click等在模板中使用该控制器的回调.在这里找到答案.


Don*_*laX 13

只想在控制器初始化两次时添加一个案例(这对于angular.js 1.3.1来说是实际的):

<div ng-if="loading">Loading...</div>
<div ng-if="!loading">
    <div ng-view></div>
</div>
Run Code Online (Sandbox Code Playgroud)

在这种情况下,当ng-view将初始化时,将设置$ route.current.这导致双重初始化.

要修复它,只需更改ng-if到ng-show/ng-hide,一切都会正常工作.


gb2*_*b2d 7

想补充参考:

双控制器代码执行也可以通过在也在页面上运行的指令中引用控制器来引起.

例如

return {

            restrict: 'A',
            controller: 'myController',
            link: function ($scope) { ....
Run Code Online (Sandbox Code Playgroud)

你的HTML中也有ng-controller ="myController"


fra*_*acz 7

当使用带有Angular 1.3+的angular-ui-router时,在路由转换时出现两次渲染视图的问题.这导致执行控制器两次.所提议的解决方案都不适合我.

但是,angular-ui-router从0.2.11 更新到0.2.13解决了我的问题.


Lew*_*wis 6

我把我的应用程序和所有依赖项都撕成了这个问题(详情请参阅:AngularJS应用程序启动两次(尝试通常的解决方案......))

最后,这是所有Batarang Chrome插件的错.

这个答案的决议:

我强烈建议任何人的清单上的第一件事是在更改代码之前根据帖子禁用它.


小智 5

如果您知道控制器无意中执行了多次,请尝试在文件中搜索有问题的控制器的名称,例如:search:MyController遍历所有文件。可能它已复制粘贴到其他html / js文件中,而您在开发或使用这些部件/控制器时却忘记了对其进行更改。资料来源:我犯了这个错误


ath*_*aki 5

我有一个相同的问题,在一个简单的应用程序(没有路由和简单的ng控制器参考)和我的控制器的构造函数确实运行了两次.最后,我发现我的问题是以下声明在我的Razor视图中自动引导我的AngularJS应用程序

<html ng-app="mTest1">
Run Code Online (Sandbox Code Playgroud)

我也使用angular.bootstrap即手动引导它

angular.bootstrap(document, [this.app.name]);
Run Code Online (Sandbox Code Playgroud)

所以删除其中一个,它对我有用.