AngularJS yürütme denetleyicisiyle iki kez mücadele


532

AngularJS'nin bazı kodları iki kez, bazen daha da fazla, $watcholaylar gibi , model durumlarını sürekli olarak kontrol ettiğini anlıyorum .

Ancak benim kod:

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

//...

DB'ye 2 kayıt ekleyerek iki kez yürütülür. Uzun zamandır kafamı buna karşı koyduğum için hala öğreniyorum!


104
Denetleyiciniz iki kez çalışıyorsa, Açısal uygulamanızı iki kez başlatmadığınızdan emin olun ( ng-appmanuel önyükleme ile ve manuel önyükleme ile otomatik olarak başlatılmasını sağlayarak ). Ayrıca denetleyicinizi birden çok öğeye (ng denetleyicisiyle) bağlayıp bağlamadığınızı kontrol edin.
Stewie

7
ne demek istediğini "ve manuel bootstrap ile" açıklayabilir misin?
spor


2
Günlüğe kaydetme ve konsol günlüklerinin iki kez yangın günlüklerini görmeyle ilgili bir sorunu giderirken devraldığım bir uygulamadaki yinelenen denetleyici davranışını fark ettim. İlk kütük ateşinin bir değeri vardı, ancak ikincisi tanımsızdı. Denetleyicinin HTML ng denetleyicisi yönergesini kaldırdıktan sonra, tanımlanmamış ikinci konsol günlük yangını ortadan kalktı.
Daniel Nalbach

2
angular.js iki kez ekleniyorsa, bu da olabilir
Mohit

Yanıtlar:


1050

Uygulama yönlendiricisi aşağıdaki MyControllergibi gezinmeyi belirtti :

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

Ama ben de vardı home.html:

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

Bu, kontrol cihazını iki kez sindirdi. data-ng-controllerÖzniteliğin HTML'den kaldırılması sorunu çözdü. Alternatif olarak, controller:mülk yönlendirme yönergesinden çıkarılmış olabilir.

Bu sorun sekmeli gezinmeyi kullanırken de ortaya çıkar. Örneğin, app.jsaşağıdakileri içerebilir:

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

İlgili raporlar sekmesi HTML'si aşağıdakine benzeyebilir:

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

Bu, kontrolörün iki kez çalıştırılmasına da neden olacaktır.


4
Bu nasıl diye sorma, kodumu tarama birçok saat sonra bu bırakmak en iyi yer, görünüyor, ama değişmek zaman <div ng-view>...için <div class="ng-view">..., bu konunun benim için durdu. Bu davranışa daha önce rastlamadım, ama belki başka biri de buna sahiptir.
Phix


1
Rotada bir denetleyici ve daha sonra html sayfasının kendisinde başka bir denetleyici bildirmenin herhangi bir yolu var mı? Hem çalışmayı hem de çatışmayı nasıl önleyebiliriz? Yoksa bu gereksiz mi?
Düşünür

1
Muhtemelen gereksizdir, belki bunun yerine birkaç direktif kullanın?
Greg

2
@Josh HTML'de bırakmak esnekliği azaltır. Şablonunuzu doğrudan bir denetleyiciye bağlıyorsunuz. Yönlendirme ile sözdizimi olarak ctrl kullanabilirsiniz.
Greg

127

AngularJS docs - ngController
Denetleyicileri DOM'a $ route hizmeti aracılığıyla bir rota tanımında bildirerek de ekleyebileceğinizi unutmayın. Yaygın bir hata, şablonun kendisinde ng-denetleyici kullanarak denetleyiciyi yeniden bildirmektir. Bu, denetleyicinin iki kez takılmasına ve çalıştırılmasına neden olur.

Yönerge ile ngRoute kullandığınızda ng-view, denetleyici varsayılan olarak bu dom öğesine (veya ui-router kullanıyorsanız ui-view) eklenir. Bu yüzden şablonu tekrar eklemenize gerek kalmayacak.


Yinelenen satıcı. Yazar zaten aynı şeyi söyledi. Sayfanın sonuna kadar aşağı kaydırın.
Iago

4
Açıkçası bunu yapmanın doğru yolu iken yazarın bir yan not olarak koymasını kafa karıştırıcı buldum. Dokümanlardaki alıntı soruyu açıkça cevaplıyor. Ve eminim birçok doktora bağlantı yararlı bulur.
shxfee

Bu, denetleyicinin iki kez yürütülmesi sorununu çözdü. Tek yaptığım, ng-denetleyicisini şablonda kaldırmak ve şimdi sadece bir kez yürütmekti.
torbenrudgaard

70

Ben sadece bunun üzerinden geçtim, ama sorun kabul edilen cevaptan farklıydı. Bunu düzeltmek için attığım adımları dahil etmek için bunu gelecekteki kendim için gerçekten terk ediyorum.

  1. Yedek denetleyici bildirimlerini kaldır
  2. Rotalardaki sondaki eğik çizgileri kontrol edin
  3. Kontrol ng-ifs
  4. Gereksiz sarma ng-viewçağrıları kontrol edin (Yanlışlıkla ng-viewbenim gerçek sarma bir bırakmıştı ng-view. Bu benim denetleyicileri için üç çağrı sonuçlandı.)
  5. Eğer Ruby on iseniz, kaldırmalısınız turbolinkssizin gelen mücevher application.jsdosyası. Bunu keşfetmek için bir gün harcadım. Burada cevap bulundu .
  6. Ng-app ve bootstrap ile uygulamayı iki kez başlatma. AngularJS yürütme denetleyicisiyle iki kez mücadele
  7. Ayrıca şablon aracılığıyla ng tıklama vb Bulunan cevaplarken kontrolörün kendi denetleyici tanımlanan ve kullanımları geri aramalar sahiptir direktifin link'-fonksiyonu' bütün elemana $ derleme kullanırken burada .

5. Rails iseniz, turbolinksgem application.jsdosyanızdan kaldırmak gerekir . Bu beni çıldırdı, keşfetmek için bütün gün boşa harcadım. Gerçek acı. Burada
18augst

6. ng-app ve bootstrap ile uygulamayı iki kez başlatma. stackoverflow.com/questions/15535336/…
thadeuszlay

1
Teşekkürler . Benim için işe yarayan şey rotanın sonuna eğik çizgi
yapmaktı

Teşekkürler bir milyon, başımın üstesinden geldi. 7 numara oldu! (her zaman sonuncusu ...).
Rabbi Shuki Gur

Vay canına, ister inanın ister inanmayın , listenizdeki her şeyi inceledim ve hala sorunu yaşıyorum.
Jacob Stamm

14

Denetleyicinin iki kez başlayabileceği bir durum daha eklemek istiyorum (bu angular.js 1.3.1 için geçerlidir):

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

Bu durumda, ng-view başlayacağı zaman $ route.current ayarlanır. Bu çift başlatmaya neden olur.

Düzeltmek için sadece ng-show / ng-hide olarak değiştirin ve hepsi iyi çalışır.


Bana yardımcı oldu, ng-show yerine ng-show / ng-hide kullanıyordum, iki ng-görünümü vardı, bir probleme değil ama ng-show / ng-hide yokken ng-if devre dışı bırakılırsa
Dimitri Kopriwa

Bir ton teşekkürler. Bu yaklaşım sorunumu çözdü. Aynı ui-viewiki kez deniyordu kontrolörü iki kez çağırdı.
curlyreggie

7

Referans için eklemek ister misiniz:

Çift denetleyici kodunun yürütülmesi, denetleyicinin sayfada da çalışan bir yönergeye başvurularak da kaynaklanabilir.

Örneğin

return {

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

HTML'nizde ng-controller = "myController" olduğunda


bunun çözümü nedir?
Sagar Bhosale

1
Yalnızca birini veya diğerini kullanın.
gb2d


6

Uygulamamı ve tüm bağımlılıklarını bu konudaki bitlere yırttım (ayrıntılar burada: AngularJS uygulaması iki kez başlatılıyor (normal çözümleri denedi ..) )

Ve sonunda, hepsi Batarang Chrome eklentisinin hatasıydı.

Çözünürlük Bu cevap :

Kimsenin listesindeki ilk şey, kodu değiştirmeden önce yazı başına devre dışı bırakmaktır.


Bu benim sorunumdu. Eklenti, açısal uygulamanızın çift örneğini çalıştırır, böylece kapsam bilgisi sağlayabilir (neden yalnızca ilk örneği kullanamayacağını bilmiyorum).
rgdigital

Yardımcı olduđuna sevindim, bunu çözmem çok zaman aldý.
Lewis

5

Denetleyicinizin istemeden birden fazla kez yürüttüğünü biliyorsanız, dosyalarınız arasında rahatsız edici denetleyicinin adını aramayı deneyin, örn: arama: Tüm dosyalar aracılığıyla MyController. Muhtemelen başka bir html / js dosyasına kopyalanmış ve bu kısmi / denetleyicileri geliştirmeye veya kullanmaya başladığınızda değiştirmeyi unuttunuz. Kaynak: Bu hatayı yaptım


5

Aynı problemi, basit bir uygulamada (yönlendirme ve basit bir ng-denetleyici referansı olmadan) yaşadım ve denetleyicimin yapıcısı iki kez çalıştı. Son olarak, sorunumun Razor görünümümde AngularJS uygulamamı otomatik önyüklemek için aşağıdaki bildiri olduğunu öğrendim

<html ng-app="mTest1">

Ben de elle açısal.bootstrap yani kullanarak bootstrapped var

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

bunlardan birini kaldırmak benim için işe yaradı.


4

Bazı durumlarda direktifiniz iki kere çalışır, sadece düzelmezseniz size şu gibi yönerge verin:

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

Bu, direktifinizi iki kez çalıştıracaktır. Ayrıca direktifinizin iki kez çalıştığı başka bir durum daha vardır:

direktifinizi index.html TWICE ürününüze dahil etmediğinizden emin olun !


Ayrıca UI-Router kullanıyorsanız, bir sınıf içindeki ui-görünümü için yönerge adı belirtmek çift yürütme ile sonuçlanıyor gibi görünmektedir. Bunu E veya <ui-view> </ui-view> olarak değiştirmek çift yürütme sorununu çözer.
SteveGSD

2

AngularJS 1.4 rc derleme ile bu sorun üzerinde başımı kaşıyor, daha sonra bu cevapların Angular 1.4 ve Angular 2 için yeni yönlendirici kitaplığından kaynaklandığından yukarıdaki cevapların hiçbirinin uygulanabilir olmadığını fark etti . Bu nedenle, burada yeni Açısal yol kitaplığını kullanan herkes için bir not bırakıyorum.

Temel olarak, bir html sayfası ng-viewportuygulamanızın bölümlerini yüklemek için bir yönerge içeriyorsa , ile belirtilen bir köprüye tıklamak ng-link, ilişkili bileşenin hedef denetleyicisinin iki kez yüklenmesine neden olur. Küçük fark, tarayıcı hedef kontrol cihazını zaten yüklediyse, aynı köprüyü yeniden tıklatarak kontrol cihazını yalnızca bir kez çağırır.

Henüz uygun bir geçici çözüm bulamadım, ancak bu davranışın shaunxu tarafından yapılan gözlemle tutarlı olduğuna inanıyorum ve umarım bu sorun, yeni rota kütüphanesinin gelecekteki yapısında ve AngularJS 1.4 sürümleriyle birlikte çözülecektir.


2

Benim durumumda, aynı denetleyiciyi kullanarak iki görünüm buldum.

$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'
    }
  }
});

2

Karşılaştığım sorun teğetsel olabilir, ancak googling beni bu soruya getirdiğinden, bu uygun olabilir. Sorun, UI Router'ı kullanırken benim için çirkin kafasını ortaya çıkarıyor, ancak yalnızca tarayıcı yenileme düğmesiyle sayfayı yenilemeye çalıştığımda. Uygulama, bir üst soyut durumuyla UI Router'ı kullanır ve daha sonra alt, üst öğeyi belirtir. Uygulama run()işlevinde bir $state.go('...child-state...')komut vardır. Ana devlet a kullanır resolveve ilk başta belki bir çocuk denetleyicisinin iki kez yürüttüğünü düşündüm.

URL karma eklenmeden önce her şey yolunda.
www.someoldwebaddress.org

Ardından, url UI Router tarafından değiştirildikten sonra,
www.someoldwebaddress.org#/childstate

... ve sayfayı tarayıcı yenileme düğmesiyle yenilediğimde , $stateChangeStartiki kez tetiklenir ve her seferinde childstate.

resolveEbeveyn durumuna iki kez ateş budur.

Belki de bu bir çamurdur; ne olursa olsun, bu benim için sorunu ortadan kaldırmak gibi görünüyor: $stateProviderilk çağrılan kod alanında , önce window.location.hash boş bir dize olup olmadığını kontrol edin . Eğer öyleyse, her şey iyidir; değilse, window.location.hash dosyasını boş bir dizeye ayarlayın. Sonra $statesadece iki kez yerine bir yere gitmek için çalışır gibi görünüyor .

Uygulamanın varsayılan güvenmek istemiyorsanız Ayrıca, runve state.go(...), sen karma değerini yakalamak ve sadece sayfa yenileme önce bulunduğu çocuk durumunu belirlemek için karma değerini kullanın ve bölgede bir koşul ekleyin deneyebilirsiniz senin kodunu ayarladığınız yer state.go(...).


1

Benim durumumda kullandığım url modeli yüzünden

url'm / ui / project /: parametre1 /: parametre2 gibiydi.

Tüm devlet değişikliği vakalarında paramerter2'ye ihtiyacım yoktu. İkinci parametreye ihtiyaç duymadığım durumlarda URL'm / ui / project /: parametre1 / gibi olur. Durum değişikliği yaptığımda kontrol cihazımı iki kez yenileyeceğim.

Çözüm, parametre2'yi boş dize olarak ayarlamak ve durum değişikliğini yapmaktı.


1

Bu çifte başlatmanın farklı bir nedenle gerçekleşmesini sağladım. Uygulamamdaki bazı rota geçişleri için, sayfanın üst kısmına doğru kaydırmayı zorlamak istedim (örneğin, sayfalandırılmış arama sonuçlarında ... İleri'yi tıklamak sizi sayfa 2'nin en üstüne götürmelidir).

Bunu $rootScope $on $viewContentLoaded(belirli koşullara göre) yürütülmüş bir dinleyici ekleyerek yaptım

$location.hash('top');

Yanlışlıkla bu, rotalarımın yeniden değerlendirilmesine ve denetleyicilerin yeniden başlatılmasına neden oluyordu



1

Benim durumumda denetleyiciyi farklı bir adla yeniden adlandırmak sorunu çözdü.

Bir yoktu kontrolör isimlerin çatışma "ile açısal-ui-tree " modülü: Ben "den "CatalogerTreeController" benim denetleyicisi adını TreeController " ve sonra da bu denetleyicisi "sayfasında iki defa başlatılması başlar ui-tree " yönergesi nedeniyle kullanılan bu yönerge " TreeController " adlı denetleyiciyi kullanır .


1

ControllerAs sözdizimini kullananlar için, $ routeprovider içindeki denetleyici etiketini aşağıdaki gibi bildirmeniz yeterlidir:

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

veya

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

$ Routeprovider öğesini bildirdikten sonra, denetleyiciyi görünümde olduğu gibi vermeyin. Bunun yerine etiketi görünümde kullanın.


0

Aynı sorunu yaşadım ve tüm cevapları denedikten sonra sonunda aynı denetleyiciye bağlı bir yönerge buldum.

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

Yönerge kaldırıldıktan sonra kontrolörün iki kez çağrılması durduruldu. Şimdi sorum şu, bu yönergeyi bu sorun olmadan denetleyici kapsamına nasıl bağlayabilirim?


0

Sadece benimkini çözdüm, ki bu aslında oldukça hayal kırıklığı yarattı. Bu bir iyonik hibrid uygulaması, ui-yönlendirici v0.2.13 kullandım. Benim durumumda, kitap kütüphaneme gidip başka bir kitap seçtikten sonra sürekli olarak "belge bulunamadı" bildiren bir epub okuyucu (epub.js kullanarak) var. Yeniden yüklediğimde, tarayıcı kitabı mükemmel bir şekilde işleniyordu, ancak başka bir kitap seçtiğimde aynı sorunu tekrar aldım.

Benim çözümüm çok basitti. Sadece kaldırıldı reload:truegelen $state.go("app.reader", { fileName: fn, reload: true });bölümümdeLibraryController


0

Ben de aynı sorunu var angular-route@1.6.7, çünkü regex yolun sonunda ekstra eğik çizgi :

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

için

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

ve düzgün çalışıyor.


0

Sadece davamı buraya ekleyerek:

Kullanıyordum açısal ui-yönlendirici ile$state.go('new_state', {foo: "foo@bar"})

Eklediğim kez encodeURIComponent parametresine, sorun gitmişti: $state.go('new_state', {foo: encodeURIComponent("foo@bar")}).

Ne oldu? URL'lerde parametre değerindeki "@" karakterine izin verilmiyor. Sonuç olarak, açısal-ui-yönlendirici denetleyicimi iki kez yarattı: ilk oluşturma sırasında orijinal "foo @ bar" ı geçti, ikinci oluşturma sırasında "foo% 40bar" kodlu sürümünü geçecekti. Parametreyi yukarıda gösterildiği gibi açıkça kodladıktan sonra sorun ortadan kalktı.


-1

Benim iki kez çağrılıyor anladım çünkü benim html iki kez yöntemi çağırıyordu çünkü.

`<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>`

Vurgulanan bölüm findX () işlevinin iki kez çağrılmasına neden oluyordu. Umarım birine yardımcı olur.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.