ChatGPT解决这个技术问题 Extra ChatGPT

对抗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);
});

//...

执行两次,将 2 条记录插入我的数据库。我显然仍在学习,因为我多年来一直在努力解决这个问题!

如果您的控制器运行了两次,请检查您是否没有两次初始化您的 Angular 应用程序(通过使用 ng-app 和手动引导程序自动初始化它)。还要检查您是否已将控制器附加到多个元素(使用 ng-controller)。
你能解释一下“和手动引导”是什么意思吗?
在解决日志记录问题并看到控制台日志触发两次时,我注意到我继承的应用程序中的重复控制器行为。第一个日志火灾有一个值,但第二个未定义。删除控制器的 HTML ng-controller 指令后,未定义的第二个控制台日志触发消失了。
如果 angular.js 被添加两次,那么这也可能发生

D
Dave Jarvis

应用路由器指定导航到 MyController,如下所示:

$routeProvider.when('/',
                   { templateUrl: 'pages/home.html',
                     controller: MyController });

但我在 home.html 中也有这个:

<div data-ng-controller="MyController">

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

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

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

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

<ion-view view-title="Reports">
  <ion-content ng-controller="ReportsCtrl">

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


这似乎是最好的地方,在梳理了我的代码几个小时后,不要问我怎么做,但是当我将 <div ng-view>... 更改为 <div class="ng-view">... 时,这个问题就停止了。我以前没有遇到过这种行为,但也许其他人也有这种行为。
在 ngController 的文档中有一个很好的解释,docs.angularjs.org/api/ng/directive/ngController
有什么方法可以在路由中声明一个控制器,然后在 html 页面本身上声明另一个控制器?如何确保两者都有效且没有冲突?或者这是不必要的?
这可能是不必要的,也许使用几个指令来代替?
@Josh 将其留在 HTML 中会降低灵活性。您将模板直接绑定到一个控制器。您可以使用 ctrl 作为路由的语法。
D
Daniel Nalbach

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

当您使用带有 ng-view 指令的 ngRoute 时,控制器默认附加到该 dom 元素(如果您使用 ui-router,则附加到 ui-view)。因此,您无需在模板中再次附加它。


重复的答案。作者已经回复了同样的说法。只需向下滚动直到页面末尾。
我发现作者将其作为旁注令人困惑,而这显然是正确的做法。文档中的引用清楚地回答了这个问题。我相信很多人会发现该文档的链接很有帮助。
这解决了我的控制器被执行两次的问题。我所做的只是删除模板中的 ng-controller,现在它只执行一次。
C
Community

我刚刚经历了这个,但问题与接受的答案不同。我真的要把它留在这里,为了我未来的自己,包括我修复它所经历的步骤。

删除多余的控制器声明 检查路由中的尾部斜杠 检查 ng-ifs 检查任何不必要的包装 ng-view 调用(我不小心留在了包装我的实际 ng-view 的 ng-view 中。这导致对我的控制器的三个调用.) 如果你在 Rails 上,你应该从你的 application.js 文件中删除 turbolinks gem。我浪费了一整天的时间来发现这一点。在这里找到答案。使用 ng-app 和 bootstrap 初始化应用程序两次。对抗 AngularJS 执行控制器两次当在指令的“链接”函数中对整个元素使用 $compile 时,该指令还定义了自己的控制器,并通过 ng-click 等在模板中使用该控制器的回调。在这里找到答案。


5. 如果你在 Rails 上,你应该从你的 application.js 文件中删除 turbolinks gem。这让我发疯,浪费了一整天的时间来发现这一点。真正的痛苦。找到答案 here
6. 使用 ng-app 和 bootstrap 初始化应用程序两次。 stackoverflow.com/questions/15535336/…
谢谢 。对我来说,有效的方法是在路线的尽头加上斜线
谢谢一百万,这让我很头疼。最终成为第 7 名! (总是最后一个......)。
哇,信不信由你,我浏览了你清单上的所有内容,但我仍然遇到问题。
D
DontRelaX

只想在控制器可以初始化两次时再添加一种情况(这对于 angular.js 1.3.1 来说是实际的):

<div ng-if="loading">Loading...</div>
<div ng-if="!loading">
    <div ng-view></div>
</div>

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

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


它帮助了我,我使用 ng-show / ng-hide 而不是 ng-if,我有两个 ng-view,这不是问题,但 ng-if 禁用,而 ng-show/ng-hide 没有
万分感谢。这种方法解决了我的问题。两次调用相同的 ui-view 两次调用控制器。
g
gb2d

想补充以供参考:

在页面上运行的指令中引用控制器也可能导致双重控制器代码执行。

例如

return {

            restrict: 'A',
            controller: 'myController',
            link: function ($scope) { ....

当您的 HTML 中也有 ng-controller="myController" 时


解决方案是什么?
仅使用其中一种。
f
fracz

angular-ui-router 与 Angular 1.3+ 一起使用时,存在关于 Rendering views twice on route transition 的问题。这也导致两次执行控制器。建议的解决方案都不适合我。

但是,将 angular-ui-router 从 0.2.11 更新到 0.2.13 为我解决了问题。


C
Community

我在这个问题上撕毁了我的应用程序及其所有依赖项(详细信息:AngularJS app initiating twice (tried the usual solutions..)

最后,这都是 Batarang Chrome 插件的错。

this answer 中的分辨率:

https://i.stack.imgur.com/AWufV.png

我强烈建议任何人列表中的第一件事是在更改代码之前根据帖子禁用它。


这是我的问题。该插件运行您的 Angular 应用程序的双重实例,因此它可以提供范围信息(不知道为什么它不能只使用初始实例)。
我很高兴它有所帮助,我花了很长时间才弄清楚这一点。
u
user3901016

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


a
athina.bikaki

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

<html ng-app="mTest1">

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

angular.bootstrap(document, [this.app.name]);

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


p
pleerock

在某些情况下,当您根本不正确关闭您的指令时,您的指令会运行两次,如下所示:

<my-directive>Some content<my-directive>

这将运行您的指令两次。当您的指令运行两次时,还有另一种常见情况:

确保您的 index.html TWICE 中没有包含您的指令!


此外,如果您使用的是 UI-Router,在类中为 ui-view 指定指令名称似乎会导致双重执行。将其更改为 E 或 可修复双重执行问题。
c
codeful.element

一直在用 AngularJS 1.4 rc build 解决这个问题,然后意识到上述答案都不适用,因为它在撰写本文时源自 new router library for Angular 1.4 and Angular 2。因此,我在这里为可能正在使用新的 Angular 路由库的任何人做一个说明。

基本上,如果 html 页面包含用于加载应用程序部分的 ng-viewport 指令,则单击 ng-link 中指定的超链接会导致相关组件的目标控制器被加载两次。细微的差别在于,如果浏览器已经加载了目标控制器,通过重新点击同一个超链接只会调用一次控制器。

尚未找到可行的解决方法,但我相信此行为与 shaunxu 提出的观察结果一致,希望此问题将在新路由库的未来构建以及 AngularJS 1.4 版本中得到解决。


L
Luke Eller

就我而言,我发现两个视图使用同一个控制器。

$stateProvider.state('app', {
  url: '',
  views: {
    "viewOne@app": {
      controller: 'CtrlOne as CtrlOne',
      templateUrl: 'main/one.tpl.html'
    },
    "viewTwo@app": {
      controller: 'CtrlOne as CtrlOne',
      templateUrl: 'main/two.tpl.html'
    }
  }
});

m
mg1075

我遇到的问题可能是切题的,但由于谷歌搜索让我想到了这个问题,这可能是合适的。使用 UI Router 时,问题对我来说很丑陋,但只有当我尝试使用浏览器刷新按钮刷新页面时。该应用程序使用带有父抽象状态的 UI 路由器,然后是父抽象状态的子状态。在应用程序 run() 函数上,有一个 $state.go('...child-state...') 命令。父状态使用 resolve,起初我认为可能是子控制器执行了两次。

在 URL 附加哈希之前一切正常。
www.someoldwebaddress.org

然后,一旦 UI 路由器修改了 URL,
www.someoldwebaddress.org#/childstate

...然后当我使用浏览器刷新按钮刷新页面时,$stateChangeStart 会触发两次,每次都指向 childstate

父状态上的 resolve 是触发两次的原因。

也许这是一个杂牌;无论如何,这似乎确实消除了我的问题:在第一次调用 $stateProvider 的代码区域中,首先检查 window.location.hash是一个空字符串。如果是,一切都很好;如果不是,则将 window.location.hash 设置为空字符串。然后看起来 $state 只尝试去某个地方一次而不是两次。

此外,如果您不想依赖应用程序的默认 runstate.go(...),您可以尝试捕获哈希值并使用哈希值来确定您在页面刷新之前所处的子状态,并添加条件到您设置 state.go(...) 的代码中的区域。


M
M. Arnold

对于那些使用 ControllerAs 语法的人,只需在 $routeprovider 中声明控制器标签,如下所示:

$routeprovider
        .when('/link', {
            templateUrl: 'templateUrl',
            controller: 'UploadsController as ctrl'
        })

或者

$routeprovider
        .when('/link', {
            templateUrl: 'templateUrl',
            controller: 'UploadsController'
            controllerAs: 'ctrl'
        })

声明 $routeprovider 后,不要像在视图中那样提供控制器。而是使用视图中的标签。


S
Sherin Syriac

就我而言,这是因为我使用的 url 模式

我的网址就像 /ui/project/:parameter1/:parameter2。

在所有状态变化的情况下,我都不需要 paramerter2。在我不需要第二个参数的情况下,我的 url 将类似于 /ui/project/:parameter1/。所以每当我有状态改变时,我都会让我的控制器刷新两次。

解决方案是将 parameter2 设置为空字符串并进行状态更改。


H
Harry Lime

由于不同的原因,我发生了这种双重初始化。对于我的应用程序中的一些路由转换,我想强制滚动到页面顶部附近(例如,在分页搜索结果中......单击下一步应该将您带到第 2 页的顶部)。

我通过向 $rootScope $on $viewContentLoaded 添加一个侦听器来做到这一点,该侦听器(基于某些条件)执行

$location.hash('top');

无意中,这导致我的路线被重新评估并且控制器被重新初始化


C
Community

我的问题是像这样更新搜索参数 $location.search('param', key);

你可以在这里读更多关于它的内容

controller getting called twice due to append params in url


A
AlexDEV.pro

在我的情况下,将控制器重命名为不同的名称解决了这个问题。

控制器名称与“angular-ui-tree”模块存在冲突:我将控制器从“CatalogerTreeController”重命名为“TreeController”,然后该控制器开始在使用“ui-tree”指令的页面上启动两次,因为该指令使用名为“TreeController”的控制器。


k
kernal_lora

我遇到了同样的问题,在尝试了所有答案后,我终于发现我的视图中有一个绑定到同一个控制器的指令。

APP.directive('MyDirective', function() {
  return {
    restrict: 'AE',
    scope: {},
    templateUrl: '../views/quiz.html',
    controller: 'ShowClassController'
}
});

删除指令后,控制器停止被调用两次。现在我的问题是,如何使用绑定到控制器范围的这个指令而没有这个问题?


m
maksbd19

我刚刚解决了我的问题,这实际上非常令人失望。它是一个离子混合应用程序,我使用了 ui-router v0.2.13。在我的例子中,有一个 epub 阅读器(使用 epub.js)在我导航到我的图书库并选择任何其他书时不断报告“未找到文档”。当我重新加载浏览器书时,它被完美呈现,但是当我选择另一本书时,又遇到了同样的问题。

我的解决方法很简单。我刚刚从我的 LibraryController 中的 $state.go("app.reader", { fileName: fn, reload: true }); 中删除了 reload:true


B
B.Ma

我在 angular-route@1.6.7 中遇到了同样的问题,这是因为正则表达式路径末尾的 extra slash

.when('/goods/publish/:classId/', option)

.when('/goods/publish/:classId', option)

它工作正常。


T
Tom

只需在此处添加我的案例:

我在 $state.go('new_state', {foo: "foo@bar"}) 中使用 angular-ui-router

encodeURIComponent 添加到参数后,问题就消失了:$state.go('new_state', {foo: encodeURIComponent("foo@bar")})

发生了什么? URL 中不允许参数值中的字符“@”。结果,angular-ui-router 两次创建了我的控制器:在第一次创建期间它传递了原始的“foo@bar”,在第二次创建期间它将传递编码版本“foo%40bar”。一旦我如上所示明确编码参数,问题就消失了。


D
Dumber_Texan2

我的问题真的很难追查。最后,当网页缺少图像时,问题就出现了。 src 缺少 URL。这发生在 MVC 5 Web 控制器上。为了解决这个问题,当没有真实图像可用时,我包含了透明图像。

<img alt="" class="logo" src="">

N
Nandu Prajapati

我发现我的被调用了两次是因为我从我的 html 中调用了两次该方法。

`<form class="form-horizontal" name="x" ng-submit="findX() novalidate >
 <input type="text"....>
 <input type="text"....>
 <input type="text"....>
 <button type="submit" class="btn btn-sm btn-primary" ng-click="findX()"
</form>`

突出显示的部分导致 findX() 被调用两次。希望它可以帮助某人。