Я понимаю, что 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 записи в мою БД. Я, очевидно, все еще участвую, поскольку я уже давно натыкаюсь на эту голову!
Маршрутизатор приложения указал навигацию на MyController
следующим образом:
$routeProvider.when('/',
{ templateUrl: 'pages/home.html',
controller: MyController });
Но у меня также было это в home.html
:
<div data-ng-controller="MyController">
Это дважды обработало контроллер. Удаление атрибута data-ng-controller
из HTML разрешило проблему. В качестве альтернативы, свойство 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">...
, этот вопрос остановился для меня. Я не сталкивался с таким поведением раньше, но, возможно, кто-то еще имеет это.
AngularJS docs - ngController
Обратите внимание, что вы также можете подключить контроллеры к DOM, объявив его в определении маршрута через службу $route. Общей ошибкой является снова объявить контроллер с помощью ng-контроллера в шаблоне сам. Это приведет к подключению и выполнению контроллера в два раза.
Когда вы используете ngRoute с директивой ng-view
, контроллер присоединяется к этому элементу dom по умолчанию (или ui-view, если вы используете ui-router). Поэтому вам не нужно будет прикреплять его снова в шаблоне.
Я просто прошел через это, но проблема была отличной от принятого ответа. Я действительно оставляю это здесь для своего будущего себя, чтобы включить шаги, которые я прошел, чтобы исправить это.
ng-ifs
ng-view
(я случайно оставил в ng-view
, который обертывал мой фактический ng-view
. Это привело к трем вызовам моих контроллеров.)turbolinks
из вашего файла application.js
. Я потратил целый день на это. Найден ответ здесь.turbolinks
из файла application.js
. Это сделало меня сумасшедшим, потратил впустую целый день, чтобы обнаружить это. Настоящая боль. Нашел ответ здесь
Просто хочу добавить еще один случай, когда контроллер может инициализировать дважды (это актуально для 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 и все будет работать хорошо.
ui-view
который дважды вызывал контроллер.
При использовании angular -ui-router с Angular 1.3+ возникла проблема с представлением рендеринга дважды по маршруту перехода. Это привело к тому, что два раза исполнили контроллеры. Ни один из предлагаемых решений не работал у меня.
Однако обновление angular-ui-router
от 0.2.11 до 0.2.13 разрешило проблему для меня.
Хотелось бы добавить для справки:
Выполнение кода двойного контроллера также может быть вызвано ссылкой на контроллер в директиве, которая также выполняется на странице.
например.
return {
restrict: 'A',
controller: 'myController',
link: function ($scope) { ....
Когда у вас также есть ng-controller = "myController" в вашем HTML
Я порвал свое приложение и все его зависимости от бит над этой проблемой (подробности здесь: Приложение AngularJS запускается дважды (пробовали обычные решения..))
И, в конце концов, это была ошибка Bartang Chrome.
Разрешение в этом ответе:
Я бы настоятельно рекомендовал, чтобы первое, что было в любом списке, это отключить его для публикации перед изменением кода.
У меня была такая же проблема, в простом приложении (без маршрутизации и простой ссылки на ng-controller), и мой конструктор контроллера выполнялся дважды. Наконец, я узнал, что моя проблема заключалась в следующем объявлении автозагрузки моего приложения AngularJS в моем представлении Razor
<html ng-app="mTest1">
Я также вручную загрузил его с помощью angular.bootstrap i.e.
angular.bootstrap(document, [this.app.name]);
поэтому удалив один из них, он работал у меня.
В некоторых случаях ваша директива выполняется дважды, когда вы просто не исправляете свою директиву так:
<my-directive>Some content<my-directive>
Это приведет к удвоению вашей директивы. Также есть еще один случай, когда ваша директива выполняется дважды:
убедитесь, что вы не указали свою директиву в index.html
TWICE!
Если вы знаете, что ваш контроллер непреднамеренно выполняет несколько раз, попробуйте выполнить поиск через ваши файлы для имени нарушающего контроллера, например: search: MyController через все файлы. Вероятно, он был скопирован в какой-то другой файл html/js, и вы забыли его изменить, когда вам нужно было разработать или использовать эти частичные/контроллеры. Источник: Я сделал эту ошибку
Проблема, с которой я сталкиваюсь, может быть тангенциальной, но, поскольку поисковая оптимизация привела меня к этому вопросу, это может быть уместно. Проблема вызывает у меня уродливую голову, когда я использую UI Router, но только когда я пытаюсь обновить страницу кнопкой обновления браузера. Приложение использует UI-маршрутизатор с родительским абстрактным состоянием, а затем дочерние элементы от родителя. В функции app run()
есть команда $state.go('...child-state...')
. В родительском состоянии используется resolve
, и сначала я думал, что, возможно, дочерний контроллер выполняет дважды.
Все в порядке, прежде чем URL-адрес будет содержать хэш. www.someoldwebaddress.org
Затем, как только URL был изменен с помощью UI Router, www.someoldwebaddress.org#/childstate
... а затем, когда я обновить страницу кнопкой обновления браузера, $stateChangeStart
срабатывает дважды, и каждый раз указывает на childstate
.
resolve
в родительском состоянии - это то, что срабатывает дважды.
Возможно, это кудря; несмотря на это, похоже, это устраняет проблему для меня: в области кода, где сначала вызывается $stateProvider
, first, чтобы проверить, есть ли window.location.hash - пустая строка. Если это так, все хорошо; если это не так, установите window.location.hash в пустую строку. Тогда кажется, что $state
пытается только один раз пойти куда-то, а не дважды.
Кроме того, если вы не хотите полагаться на приложение по умолчанию run
и state.go(...)
, вы можете попытаться захватить хеш-значение и использовать значение хэша для определения дочернего состояния, которое вы были непосредственно перед обновлением страницы, и добавьте условие в область вашего кода, где вы устанавливаете state.go(...)
.
В моем случае я нашел два представления, используя один и тот же контроллер.
$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'
}
}
});
Я почесал голову над этой проблемой с помощью AngularJS 1.4 rc build, а затем понял, что ни один из вышеприведенных ответов не применим, поскольку он был создан из новой библиотеки маршрутизаторов для Angular 1.4 и Angular 2 на момент написания этой статьи. Поэтому я оставляю примечание для всех, кто может использовать новую библиотеку маршрутов Angular.
В принципе, если html-страница содержит директиву ng-viewport
для загрузки частей вашего приложения, нажав на гиперссылку, указанную с помощью ng-link
, вы можете дважды загрузить целевой контроллер связанного компонента. Тонкая разница заключается в том, что, если браузер уже загрузил целевой контроллер, путем повторного нажатия одной и той же гиперссылки будет только один раз вызвать контроллер.
Пока не найдено жизнеспособного решения, хотя я считаю, что это поведение согласуется с наблюдением, поднятым shaunxu, и, надеюсь, эта проблема будет быть решены в будущем сборке новой библиотеки маршрутов и вместе с выпуском AngularJS 1.4.
У меня была двойная инициализация по другой причине. Для некоторых маршрутных переходов в моем приложении я хотел принудительно прокрутить до верхней части страницы (например, в постраничных результатах поиска... нажатие следующей должно привести вас к началу страницы 2).
Я сделал это, добавив слушателя к $rootScope
$on
$viewContentLoaded
, который (на основе определенных условий) выполнен
$location.hash('top');
Неосторожно это приводило к переоценке моих маршрутов и повторному инициализации контроллеров.
В моем случае это было из-за шаблона url, который я использовал
мой url был как /ui/project/: parameter1/: parameter2.
Мне не нужно параметрирование2 во всех случаях изменения состояния. В тех случаях, когда мне не нужен второй параметр, мой url был бы как /ui/project/: parameter1/. И поэтому всякий раз, когда у меня было изменение состояния, я дважды обновляю свой контроллер.
Решением было установить параметр2 как пустую строку и сделать изменение состояния.
В моем случае переименование контроллера на другое имя решило проблему.
Существовал конфликт имен контроллеров с модулем "angular -ui-tree": я переименовал мой контроллер из "CatalogerTreeController" в "TreeController", а затем этот контроллер запускается дважды на странице, где используется директива "ui-tree", поскольку в этой директиве используется контроллер с именем "TreeController".
Я понял, что мой вызов вызывает дважды, потому что я дважды вызывал метод из моего 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() дважды. Надеюсь, это поможет кому-то.
Я только что решил мой, что было на самом деле довольно разочаровывающим. Его ионное гибридное приложение, я использовал ui-router v0.2.13. В моем случае есть epub reader (с использованием epub.js), который постоянно сообщал "не найденный документ", как только я перехожу к библиотеке книг и выбираю любую другую книгу. Когда я перезагрузился, книга браузера была отлично отрисована, но когда я выбрал другую книгу, снова возникла проблема.
Мое решение было очень простым. Я просто удалил reload:true
из $state.go("app.reader", { fileName: fn, reload: true });
в мой LibraryController
Моя проблема заключалась в обновлении параметров поиска, таких как $location.search('param', key);
вы можете прочитать об этом здесь
контроллер получает вызов дважды из-за добавления параметров в URL
У меня была такая же проблема, и после того, как я попробовал все ответы, я наконец обнаружил, что у меня есть директива в моем представлении, связанная с одним и тем же контроллером.
APP.directive('MyDirective', function() {
return {
restrict: 'AE',
scope: {},
templateUrl: '../views/quiz.html',
controller: 'ShowClassController'
}
});
После удаления директивы контроллер перестает вызываться дважды. Теперь мой вопрос: как использовать эту директиву, связанную с областью контроллера без этой проблемы?
ng-app
и с помощью ручной загрузки). Также проверьте, подключен ли ваш контроллер к нескольким элементам (с помощью ng-controller).