Jaki jest właściwy sposób komunikacji między kontrolerami?
Obecnie używam okropnej krówki obejmującej window
:
function StockSubgroupCtrl($scope, $http) {
$scope.subgroups = [];
$scope.handleSubgroupsLoaded = function(data, status) {
$scope.subgroups = data;
}
$scope.fetch = function(prod_grp) {
$http.get('/api/stock/groups/' + prod_grp + '/subgroups/').success($scope.handleSubgroupsLoaded);
}
window.fetchStockSubgroups = $scope.fetch;
}
function StockGroupCtrl($scope, $http) {
...
$scope.select = function(prod_grp) {
$scope.selectedGroup = prod_grp;
window.fetchStockSubgroups(prod_grp);
}
}
Odpowiedzi:
Edycja : Problem rozwiązany w tej odpowiedzi został rozwiązany w wersji angular.js w wersji 1.2.7 .
$broadcast
teraz unika bulgotania się nad niezarejestrowanymi zakresami i działa tak szybko, jak $ emit.Teraz możesz:
$broadcast
z$rootScope
$on
lokalnego,$scope
który musi wiedzieć o wydarzeniuOryginalna odpowiedź poniżej
Radzę nie używać
$rootScope.$broadcast
+,$scope.$on
ale raczej$rootScope.$emit
+$rootScope.$on
. To pierwsze może powodować poważne problemy z wydajnością, o czym wspomniał @numan. Dzieje się tak, ponieważ wydarzenie rozbije się na wszystkie zakresy.Jednak to ostatnie (użycie
$rootScope.$emit
+$rootScope.$on
) nie cierpi z tego powodu i dlatego może być używane jako szybki kanał komunikacji!Z dokumentacji kątowej
$emit
:Ponieważ nie ma powyższego zakresu
$rootScope
, nie ma miejsca na bulgotanie. Używanie$rootScope.$emit()
/$rootScope.$on()
jako EventBus jest całkowicie bezpieczne .Jest jednak jedna gotcha, gdy używasz go z poziomu kontrolerów. Jeśli łączysz się bezpośrednio
$rootScope.$on()
z kontrolerem, musisz samodzielnie usunąć powiązanie, gdy lokalny$scope
zostanie zniszczony. Wynika to z faktu, że kontrolery (w przeciwieństwie do usług) mogą być wielokrotnie tworzone przez cały czas istnienia aplikacji, co powoduje zsumowanie powiązań, co ostatecznie spowoduje przeciek pamięci w całym miejscu :)Aby wyrejestrować, tylko słuchać na swojej
$scope
„s$destroy
zdarzenia, a następnie wywołać funkcję, który został zwrócony przez$rootScope.$on
.Powiedziałbym, że tak naprawdę nie jest to kwestia specyficzna pod kątem, ponieważ dotyczy to również innych implementacji EventBus, że musisz oczyścić zasoby.
W takich przypadkach możesz jednak ułatwić sobie życie. Na przykład, możesz małpować łatkę
$rootScope
i dać jej$onRootScope
subskrypcję zdarzeń emitowanych na,$rootScope
ale także bezpośrednio czyści program obsługi, gdy lokalny$scope
zostanie zniszczony.Najczystszym sposobem na załatanie małpy w
$rootScope
celu zapewnienia takiej$onRootScope
metody byłoby zastosowanie dekoratora (blok uruchamiania prawdopodobnie zrobi to dobrze, ale pssst, nie mów nikomu)Aby upewnić się, że
$onRootScope
właściwość nie pojawi się nieoczekiwanie podczas wyliczania ponad$scope
, używamyObject.defineProperty()
i ustawiamyenumerable
nafalse
. Pamiętaj, że możesz potrzebować podkładki ES5.Dzięki tej metodzie kod kontrolera z góry można uprościć w celu:
Dlatego jako ostateczny wynik tego wszystkiego radzę użyć
$rootScope.$emit
+$scope.$onRootScope
.Przy okazji, staram się przekonać zespół kątowy do rozwiązania problemu w rdzeniu kątowym. Trwa dyskusja tutaj: https://github.com/angular/angular.js/issues/4574
Oto jsperf, który pokazuje, jak duży wpływ
$broadcast
na stół przynosi porządny scenariusz w zaledwie 100$scope
.http://jsperf.com/rootscope-emit-vs-rootscope-broadcast
źródło
Najważniejszą odpowiedzią było obejście problemu Angular, który już nie istnieje (przynajmniej w wersjach> 1.2.16 i „prawdopodobnie wcześniej”), jak wspomniał @zumalifeguard. Ale nadal czytam wszystkie te odpowiedzi bez faktycznego rozwiązania.
Wydaje mi się, że odpowiedź powinna być teraz
$broadcast
z$rootScope
$on
lokalnego,$scope
który musi wiedzieć o wydarzeniuWięc opublikować
I subskrybuj
Plunkers
Controller As
składniaJeśli zarejestrujesz słuchacza na poziomie lokalnym
$scope
, to zostanie zniszczony automatycznie przez$destroy
siebie , gdy wiąże się kontroler zostanie usunięty.źródło
controllerAs
składnią? Byłem w stanie użyć$rootScope
subskrybenta do nasłuchiwania tego wydarzenia, ale byłem tylko ciekawy, czy istnieje inny wzorzec.$scope
bezpośrednio. John Papa pisze, że wydarzenia są jednym „wyjątkiem” od jego zwykłej zasady trzymania$scope
„z dala” od swoich kontrolerów (używam cytatów, ponieważ jak wspomina,Controller As
nadal ma$scope
to pod maską).controller as
alternatywną składnią zgodnie z żądaniem. Mam nadzieję, że o to ci chodziło.Użycie $ rootScope. $ Broadcast i $ scope. $ On do komunikacji PubSub.
Zobacz także ten post: AngularJS - Komunikacja między kontrolerami
źródło
$rootScope
i$watch
. Nie jestem pewien, czy to jakaś poprawa.Ponieważ definProperty ma problem ze zgodnością przeglądarki, myślę, że możemy pomyśleć o korzystaniu z usługi.
i użyj go w kontrolerze w następujący sposób:
kontroler 1
kontroler 2
źródło
GridLinked opublikował rozwiązanie PubSub , które wydaje się być całkiem dobrze zaprojektowane. Serwis można znaleźć tutaj .
Również schemat ich obsługi:
źródło
W rzeczywistości użycie emisji i emisji jest nieefektywne, ponieważ zdarzenie przesuwa się w górę iw dół hierarchii zasięgu, co może łatwo zmienić się w butelkę wydajności dla złożonej aplikacji.
Sugerowałbym skorzystać z usługi. Oto jak niedawno wdrożyłem go w jednym z moich projektów - https://gist.github.com/3384419 .
Podstawowy pomysł - zarejestruj autobus pubowy / eventowy jako usługę. Następnie wstrzyknij ten eventbus tam, gdzie trzeba subskrybować lub publikować wydarzenia / tematy.
źródło
$rootScope.$emit()
tylko pęcherzyki w górę. Ponieważ jednak nie ma zakresu powyżej,$rootScope
nie ma się czego bać. Więc jeśli tylko używasz$rootScope.$emit()
i$rootScope.$on()
będziesz miał szybki systemowy EventBus.$rootScope.$on()
wewnątrz kontrolera, musisz wyczyścić powiązanie zdarzenia, ponieważ w przeciwnym razie będą one sumowane, ponieważ tworzy nowe za każdym razem, gdy kontroler jest tworzony i nie zostać automatycznie zniszczony, ponieważ wiążesz się$rootScope
bezpośrednio.Korzystając z metod get i set w ramach usługi, można bardzo łatwo przekazywać wiadomości między kontrolerami.
w HTML HTML możesz to sprawdzić w ten sposób
źródło
Jeśli chodzi o oryginalny kod - wygląda na to, że chcesz udostępnić dane między zakresami. Aby udostępnić Dane lub Stan pomiędzy $ scope, dokumenty sugerują skorzystanie z usługi:
Ref: Angular Docs link tutaj
źródło
Właściwie zacząłem używać Postal.js jako magistrali komunikatów między kontrolerami.
Ma wiele zalet, takich jak szyna komunikatów, takich jak powiązania w stylu AMQP, sposób, w jaki poczta może zintegrować w / iFrame i gniazda sieciowe, i wiele innych rzeczy.
Użyłem dekoratora, żeby skonfigurować pocztę na
$scope.$bus
...Oto link do postu na blogu na ten temat ...
http://jonathancreamer.com/an-angular-event-bus-with-postal-js/
źródło
Tak to robię z Fabryką / Usługami i prostym wstrzykiwaniem zależności (DI) .
źródło
Podobał mi się sposób
$rootscope.emit
wykorzystania komunikacji wewnętrznej. Sugeruję czyste i wydajne rozwiązanie bez zanieczyszczania globalnej przestrzeni.źródło
Oto szybki i brudny sposób.
Oto przykładowa funkcja do dodania w dowolnym kontrolerze rodzeństwa:
i oczywiście jest twój HTML:
źródło
$rootScope
?Począwszy od Angular 1.5 i skupia się na rozwoju opartym na komponentach. Zalecany sposób interakcji między komponentami polega na użyciu właściwości „need” i powiązaniach właściwości (wejścia / wyjścia).
Komponent wymagałby innego komponentu (na przykład komponentu głównego) i uzyskałby odwołanie do kontrolera:
Następnie możesz użyć metod komponentu głównego w komponencie potomnym:
To jest funkcja kontrolera głównego komponentu:
Oto pełny przegląd architektury: Komunikacja komponentowa
źródło
Możesz uzyskać dostęp do tej funkcji hello w dowolnym miejscu modułu
Kontroler jeden
drugi kontroler
Więcej informacji tutaj
źródło
Stworzę usługę i użyję powiadomienia.
Ponieważ w dowolnym momencie usługa powiadomień jest pojedyncza, powinna być w stanie zapewnić utrwalone dane w całym systemie.
Mam nadzieję że to pomoże
źródło
Możesz skorzystać z wbudowanej usługi AngularJS
$rootScope
i wstrzyknąć tę usługę do obu kontrolerów. Następnie można nasłuchiwać zdarzeń uruchamianych na obiekcie $ rootScope.$ rootScope udostępnia dwa wywoływacze zdarzeń,
$emit and $broadcast
które są odpowiedzialne za wywoływanie zdarzeń (mogą być zdarzeniami niestandardowymi) i używają$rootScope.$on
funkcji do dodawania detektora zdarzeń.źródło
Powinieneś korzystać z Usługi, ponieważ
$rootscope
jest to dostęp z całej aplikacji, a to zwiększa obciążenie lub używasz rootparamów, jeśli twoich danych już nie ma.źródło
źródło
Możesz to zrobić, używając zdarzeń kątowych, które to $ emit i $ broadcast. Zgodnie z naszą wiedzą jest to najlepszy, wydajny i skuteczny sposób.
Najpierw wywołujemy funkcję z jednego kontrolera.
Możesz także użyć $ rootScope zamiast $ scope. Użyj odpowiednio kontrolera.
źródło