Przeczytałem uważnie dokumentację AngularJS na ten temat, a następnie majstrowałem przy dyrektywie. Oto skrzypce .
A oto kilka istotnych fragmentów:
Z HTML :
<pane bi-title="title" title="{{title}}">{{text}}</pane>
Z dyrektywy dotyczącej okien:
scope: { biTitle: '=', title: '@', bar: '=' },
Jest kilka rzeczy, których nie rozumiem:
- Dlaczego muszę korzystać
"{{title}}"
z'@'
i"title"
ze'='
? - Czy mogę również uzyskać bezpośredni dostęp do zakresu nadrzędnego, bez ozdabiania mojego elementu atrybutem?
- Dokumentacja mówi „Często pożądane jest przekazywanie danych z izolowanego zakresu przez wyrażenie i do zakresu nadrzędnego” , ale wydaje się, że działa to dobrze również w przypadku wiązania dwukierunkowego. Dlaczego droga ekspresowa byłaby lepsza?
Znalazłem też inne skrzypce, które pokazują rozwiązanie wyrażeń: http://jsfiddle.net/maxisam/QrCXh/
=
w dyrektywie wyodrębniono zakres, aby umożliwić dwukierunkowe wiązanie i@
nie aktualizuje modelu, jedynie aktualizuje wartości zakresu dyrektywy.Odpowiedzi:
@ wiąże właściwość zasięgu lokalnego / dyrektywy z oszacowaną wartością atrybutu DOM . Jeśli używasz
title=title1
lubtitle="title1"
, wartość atrybutu DOM „tytuł” jest po prostu łańcuchemtitle1
. Jeśli użyjesztitle="{{title}}"
, wartość atrybutu DOM „tytuł” jest wartością interpolowaną{{title}}
, a zatem ciąg będzie tym, czym jest obecnie ustawiona dowolna właściwość zakresu nadrzędnego „tytuł”. Ponieważ wartości atrybutów są zawsze ciągami, podczas korzystania z @ zawsze otrzymasz wartość ciągu dla tej właściwości w zakresie dyrektywy .= wiąże właściwość zakresu lokalnego / dyrektywy z właściwością zakresu nadrzędnego . Tak więc z = używasz nazwy właściwości modelu nadrzędnego / zakresu jako wartości atrybutu DOM. Nie możesz używać
{{}}
s z = .Za pomocą @ możesz robić takie rzeczy, jak
title="{{title}} and then some"
- {{tytuł}} jest interpolowany, a następnie ciąg „i niektóre z nich” jest z nim łączony. Ostateczny skonkatenowany ciąg jest tym, co otrzymuje właściwość zasięgu lokalnego / dyrektywy. (Nie możesz tego zrobić za pomocą = , tylko @ .)Przy @ musisz użyć,
attr.$observe('title', function(value) { ... })
jeśli chcesz użyć wartości w funkcji linkowania. Np.if(scope.title == "...")
Nie będzie działać tak, jak się spodziewasz. Pamiętaj, że oznacza to, że możesz uzyskać dostęp do tego atrybutu tylko asynchronicznie . Nie musisz używać $ observ (), jeśli używasz tylko wartości w szablonie. Nptemplate: '<div>{{title}}</div>'
.Dzięki = nie musisz używać $ observ.
Tak, ale tylko jeśli nie używasz zakresu izolowanego. Usuń ten wiersz ze swojej dyrektywy
scope: { ... }
a wtedy twoja dyrektywa nie stworzy nowego zakresu. Użyje zakresu nadrzędnego. Następnie można uzyskać bezpośredni dostęp do wszystkich właściwości zakresu nadrzędnego.
Tak, wiązanie dwukierunkowe umożliwia współużytkowanie danych przez zakres lokalny / dyrektywny i nadrzędny. „Powiązanie wyrażeń” umożliwia dyrektywie wywołanie wyrażenia (lub funkcji) zdefiniowanej przez atrybut DOM - a także można przekazać dane jako argumenty do wyrażenia lub funkcji. Jeśli więc nie musisz współdzielić danych z rodzicem - chcesz tylko wywołać funkcję zdefiniowaną w zakresie nadrzędnym - możesz użyć składni & .
Zobacz też
źródło
@
(„at”) kopiuje wartość „ATtribute”.=
(„równa się”) jest równoznaczne z twierdzeniem, że klucz jest równy wyrażeniu. Tak przynajmniej utrzymuję ich w cieśninie.foo="{{1+1}}"
- ponieważ nie potrzebujemy tutaj dwukierunkowego wiązania danych. W powyższym komentarzu starałem się podkreślić, że powinniśmy używać = tylko wtedy, gdy dyrektywa wymaga dwukierunkowego powiązania danych. Użyj @ lub w inny sposób.Istnieje wiele wspaniałych odpowiedzi tutaj, ale chciałbym zaoferować moją perspektywę na różnicach pomiędzy
@
,=
i&
wiązania, które okazały się przydatne dla mnie.Wszystkie trzy powiązania są sposobami przekazywania danych z zakresu nadrzędnego do izolowanego zakresu dyrektywy przez atrybuty elementu:
Uważam, że łatwiej jest zapamiętać te różnice, odwołując się do powiązań zakresu przez krótszy opis:
@
Wiązanie ciągu atrybutu=
Wiązanie modelu dwukierunkowego&
Powiązanie metody wywołania zwrotnegoSymbole również wyjaśniają, co zmienna zakresu reprezentuje wewnątrz implementacji twojej dyrektywy:
@
strunowy=
Model&
metodaW kolejności przydatności (w każdym razie dla mnie):
źródło
"&"
obsługuje argumenty (a raczej miejscowe) formularza:,callback({foo: "some value"})
które można by następnie wykorzystać<my-dir callback="doSomething(foo)">
. W przeciwnym razie dobra odpowiedźcallback(argument)
. Co wciąż nie jest tym samym co oncallback
sam.W
=
sposób dwukierunkowy wiążące, a więc odniesienia do zmiennej do zakresu macierzystego. Oznacza to, że jeśli zmienisz zmienną w dyrektywie, zostanie ona również zmieniona w zakresie nadrzędnym.@
oznacza, że zmienna zostanie skopiowana (sklonowana) do dyrektywy.O ile wiem, też
<pane bi-title="{{title}}" title="{{title}}">{{text}}</pane>
powinien działać.bi-title
otrzyma wartość zmiennej zakresu nadrzędnego, którą można zmienić w dyrektywie.Jeśli musisz zmienić kilka zmiennych w zakresie nadrzędnym, możesz wykonać funkcję w zakresie nadrzędnym z poziomu dyrektywy (lub przekazać dane za pośrednictwem usługi).
źródło
Jeśli chcesz zobaczyć więcej, jak to działa na przykładzie na żywo. http://jsfiddle.net/juanmendez/k6chmnch/
źródło
@
dostać jako ciąg=
2-kierunkowe wiązanie&
Zachowuje się to nieco inaczej, ponieważ zakres otrzymuje funkcję, która zwraca przekazany obiekt . Zakładam, że było to konieczne, aby działało. Skrzypce powinny to wyjaśnić.To skrzypce powinno pokazać, jak działają . Zwróć szczególną uwagę na funkcje lunety
get...
w nazwie, aby, mam nadzieję, lepiej zrozumieć, o co mi chodzi&
źródło
Istnieją trzy sposoby dodania zakresu w dyrektywie:
Dyrektywa i jej nadrzędny (kontroler / dyrektywa, w której się znajduje) zakres jest taki sam. Zatem wszelkie zmiany w zmiennych zasięgu wewnątrz dyrektywy są odzwierciedlane również w kontrolerze nadrzędnym. Nie musisz tego określać, ponieważ jest to ustawienie domyślne.
Tutaj, jeśli zmienisz zmienne zasięgu w dyrektywie, nie będzie to odzwierciedlać zakresu nadrzędnego, ale jeśli zmienisz właściwość zmiennej zasięgu, co zostanie odzwierciedlone w zakresie nadrzędnym, tak jak faktycznie zmodyfikowałeś zmienną zakresu nadrzędnego .
Przykład,
Dzieje się tak, gdy tworzysz wtyczki, ponieważ czyni to dyrektywę ogólną, ponieważ można ją umieścić w dowolnym HTML i nie ma wpływu na jej zakres nadrzędny.
Teraz, jeśli nie chcesz żadnej interakcji z zakresem nadrzędnym, możesz po prostu określić zakres jako pusty obiekt. lubić,
Przeważnie tak nie jest, ponieważ potrzebujemy interakcji z zakresem nadrzędnym, dlatego chcemy, aby niektóre wartości / zmiany zostały przekazane. Z tego powodu używamy:
@ oznacza, że zmiany z zakresu kontrolera zostaną odzwierciedlone w zakresie dyrektywy, ale jeśli zmodyfikujesz wartość w zakresie dyrektywy, zmienna zakresu kontrolera nie zostanie zmieniona.
@ zawsze oczekuje, że odwzorowany atrybut będzie wyrażeniem. To jest bardzo ważne; ponieważ aby prefiks „@” działał, musimy owinąć wartość atrybutu wewnątrz {{}}.
= jest dwukierunkowy, więc zmiana zmiennej w zakresie dyrektywy również wpływa na zmienną zakresu kontrolera
& służy do powiązania metody zakresu kontrolera, aby w razie potrzeby można ją było wywołać z dyrektywy
Zaletą jest to, że nazwa zmiennej nie musi być taka sama w zakresie kontrolera i zakresie dyrektywy.
Przykład, zakres dyrektywy ma zmienną „dirVar”, która synchronizuje się ze zmienną „contVar” zakresu kontrolera. Daje to dużą moc i uogólnienie dyrektywy, ponieważ jeden kontroler może synchronizować ze zmienną v1, podczas gdy inny kontroler używający tej samej dyrektywy może poprosić dirVar o synchronizację ze zmienną v2.
Poniżej znajduje się przykład użycia:
Dyrektywą i kontrolerem są:
I html (zauważ różnicę dla @ i =):
Oto link do bloga, który ładnie go opisuje.
źródło
Po prostu możemy użyć: -
@ : - dla wartości ciągu dla jednokierunkowego powiązania danych. w jeden sposób powiązanie danych można przekazać wartość zakresu tylko do dyrektywy
= : - dla wartości obiektu dla dwukierunkowego powiązania danych. w dwukierunkowym powiązaniu danych możesz zmienić wartość zakresu w dyrektywie, a także w html.
& : - dla metod i funkcji.
EDYTOWAĆ
W naszej definicji komponentu dla wersji kątowej 1.5 i wyższej
istnieją cztery różne typy powiązań:
=
Dwukierunkowe wiązanie danych : - jeśli zmienimy wartość, zostanie ona automatycznie zaktualizowana<
wiązanie jednokierunkowe : - gdy chcemy po prostu odczytać parametr z zakresu nadrzędnego i nie aktualizować go.@
dotyczy to parametrów ciągu&
dotyczy to wywołań zwrotnych w przypadku, gdy komponent musi wyprowadzić coś do swojego nadrzędnego zakresuźródło
Stworzyłem mały plik HTML, który zawiera kod Angulara, pokazujący różnice między nimi:
źródło
= Sposobem jest wiążący 2-drożny , który pozwala mieć żywe zmian wewnątrz dyrektywy. Kiedy ktoś zmieni tę zmienną poza dyrektywę, będziesz mieć te zmienione dane w swojej dyrektywie, ale @ way nie jest wiążące w obie strony . Działa jak tekst . Wiążesz raz, a będziesz miał tylko jego wartość.
Aby uzyskać to jaśniej, możesz skorzystać z tego wspaniałego artykułu:
Dyrektywa AngularJS Zakres „@” i „=”
źródło
To pytanie zostało już pobite na śmierć, ale i tak podzielę się nim na wypadek, gdyby ktoś jeszcze zmagał się z okropnym bałaganem, jakim są zakresy AngularJS. Pokrywa ta wola
=
,<
,@
,&
i::
. Pełny opis można znaleźć tutaj .=
ustanawia wiązanie dwukierunkowe. Zmiana właściwości w obiekcie nadrzędnym spowoduje zmianę w obiekcie podrzędnym i odwrotnie.<
ustanawia wiązanie w jedną stronę, od rodzica do dziecka. Zmiana właściwości elementu nadrzędnego spowoduje zmianę elementu podrzędnego, ale zmiana właściwości elementu podrzędnego nie wpłynie na właściwość elementu nadrzędnego.@
przypisze do właściwości potomnej wartość ciągu atrybutu tagu. Jeśli atrybut zawiera wyrażenie , właściwość potomna jest aktualizowana za każdym razem, gdy wyrażenie zmienia się na inny ciąg. Na przykład:Tutaj
description
właściwość w zakresie podrzędnym będzie bieżącą wartością wyrażenia"The movie title is {{$ctrl.movie.title}}"
, gdziemovie
jest obiektem w zakresie nadrzędnym.&
jest nieco podstępny i wydaje się, że nie ma istotnego powodu, aby kiedykolwiek z niego korzystać. Pozwala ocenić wyrażenie w zakresie nadrzędnym, zastępując parametry zmiennymi z zakresu podrzędnego. Przykład ( plunk ):Biorąc pod uwagę
parentVar=10
, wyrażenieparentFoo({myVar:5, myOtherVar:'xyz'})
będzie oceniać,5 + 10 + 'xyz'
a komponent będzie renderowany jako:Kiedy chciałbyś kiedykolwiek skorzystać z tej zawiłej funkcjonalności?
&
jest często używany przez ludzi do przekazania do zakresu potomnego funkcji wywołania zwrotnego w zakresie nadrzędnym. W rzeczywistości jednak ten sam efekt można uzyskać, używając funkcji <, aby przekazać funkcję, co jest prostsze i pozwala uniknąć nieporęcznej składni nawiasów klamrowych w celu przekazania parametrów ({myVar:5, myOtherVar:'xyz'}
). Rozważać:Oddzwonienie za pomocą
&
:Oddzwonienie za pomocą
<
:Zauważ, że obiekty (i tablice) są przekazywane przez odniesienie do zakresu potomnego, a nie kopiowane. Oznacza to, że nawet jeśli jest to wiązanie jednokierunkowe, pracujesz z tym samym obiektem w zakresie nadrzędnym i podrzędnym.
Aby zobaczyć różne prefiksy w akcji, otwórz tę paczkę .
Łączenie jednorazowe (inicjowanie) przy użyciu::
[Oficjalne dokumenty]
Późniejsze wersje AngularJS wprowadzają opcję posiadania powiązania jednorazowego, w którym właściwość zasięgu potomnego jest aktualizowana tylko raz. Poprawia to wydajność, eliminując potrzebę oglądania właściwości nadrzędnej. Składnia jest inna niż powyżej; aby zadeklarować powiązanie jednorazowe, dodajesz
::
przed wyrażeniem w znaczniku komponentu :Spowoduje to propagowanie wartości
tagline
do zasięgu potomnego bez ustanawiania wiązania jednokierunkowego lub dwukierunkowego. Uwaga : jeślitagline
początkowo znajduje sięundefined
w zakresie nadrzędnym, kątowy będzie go obserwował, dopóki się nie zmieni, a następnie dokona jednorazowej aktualizacji odpowiedniej właściwości w zakresie podrzędnym.Podsumowanie
Poniższa tabela pokazuje, jak działają przedrostki w zależności od tego, czy właściwość jest obiektem, tablicą, łańcuchem itp.
źródło
@ właściwość zakresu lokalnego służy do uzyskiwania dostępu do wartości ciągów zdefiniowanych poza dyrektywą.
= W przypadkach, w których konieczne jest utworzenie dwukierunkowego powiązania między zakresem zewnętrznym a zakresem izolowania dyrektywy, można użyć znaku =.
& Właściwość zakresu lokalnego umożliwia konsumentowi dyrektywy przekazanie funkcji, którą dyrektywa może wywołać.
Prosimy sprawdzić poniższy link, który daje jasne zrozumienie przykładów. Uważam, że jest bardzo przydatny, więc pomyślałem o udostępnieniu go.
http://weblogs.asp.net/dwahlin/creating-custom-angularjs-directives-part-2-isolate-scope
źródło
Nawet gdy zakres jest lokalny, jak w twoim przykładzie, możesz uzyskać dostęp do zakresu nadrzędnego za pośrednictwem właściwości
$parent
. Załóżmy w poniższym kodzie, którytitle
jest zdefiniowany w zakresie nadrzędnym. Następnie możesz uzyskać dostęp do tytułu jako$parent.title
:Jednak w większości przypadków ten sam efekt lepiej uzyskać za pomocą atrybutów.
Przykład, w którym znalazłem notację „&”, która jest używana „do przekazywania danych z zakresu izolowanego za pomocą wyrażenia i do zakresu nadrzędnego”, użyteczny (i nie można zastosować dwukierunkowego wiązania danych) znajduje się w dyrektywie do renderowania specjalnej struktury danych w powtórzeniu ng.
Jedną częścią renderowania był przycisk usuwania i tutaj warto było dołączyć funkcję usuwania z zakresu zewnętrznego za pomocą &. Wewnątrz dyrektywy renderowania wygląda
Dwukierunkowe wiązanie danych, tzn.
data = "="
Nie może być użyte, ponieważ funkcja usuwania działałaby w każdym$digest
cyklu, co nie jest dobre, ponieważ zapis jest natychmiast usuwany i nigdy nie renderowany.źródło
Zaimplementowałem wszystkie możliwe opcje w skrzypcach.
Zajmuje się wszystkimi opcjami:
https://jsfiddle.net/rishulmatta/v7xf2ujm
źródło
główna różnica między nimi jest sprawiedliwa
źródło
@
i=
zobacz inne odpowiedzi.Jeden haczyka o TL; DR; pobiera wyrażenie (nie tylko funkcję jak w przykładach w innych odpowiedziach) od rodzica i ustawia je jako funkcję w dyrektywie, która wywołuje to wyrażenie. Ta funkcja ma możliwość zastąpienia dowolnej zmiennej (nawet nazwy funkcji) wyrażenia poprzez przekazanie obiektu zmiennymi.
&
&
wyjaśnione
&
jest wyrazem odniesienia, co oznacza, że jeśli coś przekazać jak<myDirective expr="x==y"></myDirective>
w dyrektywie, to
expr
będzie to funkcja, która wymaga wyrażenia, jak:function expr(){return x == y}
.więc w dyrektywie HTML
<button ng-click="expr()"></button>
wywoła wyrażenie. W js dyrektywy po prostu$scope.expr()
wywoła to wyrażenie.Wyrażenie zostanie wywołane z $ scope.x i $ scope.y rodzica.
Masz możliwość zastąpienia parametrów!
Jeśli ustawisz je przez wywołanie, np
<button ng-click="expr({x:5})"></button>
. Wyrażenie zostanie wywołane z parametrem
x
i parametrem rodzicay
.Możesz zastąpić oba.
Teraz wiesz, dlaczego
<button ng-click="functionFromParent({x:5})"></button>
działa.Ponieważ po prostu wywołuje wyrażenie rodzic (np
<myDirective functionFromParent="function1(x)"></myDirective>
) i zastępuje możliwe wartości określonymi parametrami, w tym przypadkux
.może to być:
<myDirective functionFromParent="function1(x) + 5"></myDirective>
albo
<myDirective functionFromParent="function1(x) + z"></myDirective>
z rozmowy dziecka:
<button ng-click="functionFromParent({x:5, z: 4})"></button>
.lub nawet zastąpienie funkcji:
<button ng-click="functionFromParent({function1: myfn, x:5, z: 4})"></button>
.to tylko wyrażenie, nie ma znaczenia, czy jest to funkcja, wiele funkcji, czy tylko porównanie. I możesz zastąpić dowolną zmienną tego wyrażenia.
Przykłady:
dyrektywa szablon vs zwanego kodem:
rodzic zdefiniowała $ scope.x, $ scope.y:
szablon nadrzędny:
<myDirective expr="x==y"></myDirective>
<button ng-click="expr()"></button>
rozmowy$scope.x==$scope.y
<button ng-click="expr({x: 5})"></button>
rozmowy5 == $scope.y
<button ng-click="expr({x:5, y:6})"></button>
rozmowy5 == 6
rodzic zdefiniował $ scope.function1, $ scope.x, $ scope.y:
szablon nadrzędny:
<myDirective expr="function1(x) + y"></myDirective>
<button ng-click="expr()"></button>
połączeń$scope.function1($scope.x) + $scope.y
<button ng-click="expr({x: 5})"></button>
połączeń$scope.function1(5) + $scope.y
<button ng-click="expr({x:5, y:6})"></button>
Połączenia$scope.function1(5) + 6
dyrektywa ma $ scope.myFn jako funkcja:
<button ng-click="expr({function1: myFn, x:5, y:6})"></button>
połączenia$scope.myFn(5) + 6
źródło
Gdy używasz {{title}}, tylko wartość zakresu nadrzędnego zostanie przekazana do widoku dyrektywy i oceniona. Jest to ograniczone do jednego sposobu, co oznacza, że zmiana nie zostanie odzwierciedlona w zakresie nadrzędnym. Możesz użyć „=”, jeśli chcesz odzwierciedlić zmiany wprowadzone w dyrektywie podrzędnej również w zakresie nadrzędnym. To jest dwukierunkowe.
Gdy dyrektywa ma atrybut scope (zakres: {}), nie będzie już można uzyskać bezpośredniego dostępu do zakresu nadrzędnego. Ale nadal można uzyskać do niego dostęp przez zakres. $ Parent itp. Jeśli usuniesz zakres z dyrektywy, możesz uzyskać do niego bezpośredni dostęp.
To zależy od kontekstu. Jeśli chcesz wywołać wyrażenie lub funkcję z danymi, korzystasz z &, a jeśli chcesz udostępniać dane, możesz skorzystać z dwustronnego sposobu, używając „=”
Różnice między wieloma sposobami przekazywania danych do dyrektywy znajdują się pod poniższym linkiem:
AngularJS - Lunety izolowane - @ vs = vs &
http://www.codeforeach.com/angularjs/angularjs-isolated-scopes-vs-vs
źródło
@ Powiązanie ciągu atrybutu (w jedną stronę) = Powiązanie modelu dwukierunkowego i powiązanie metody wywołania zwrotnego
źródło
@ wiąże właściwość zasięgu lokalnego / dyrektywy z oszacowaną wartością atrybutu DOM. = wiąże właściwość zakresu lokalnego / dyrektywy z właściwością zakresu nadrzędnego. & bindowanie służy do przekazania metody do zakresu dyrektywy, aby można ją było wywołać w ramach dyrektywy.
@ Powiązanie ciągu atrybutu = Powiązanie modelu dwukierunkowego i powiązanie metody wywołania zwrotnego
źródło