Odpowiedzi:
@
umożliwia przekazanie wartości zdefiniowanej w atrybucie dyrektywy do izolowanego zakresu dyrektywy. Wartość może być prostą wartością ciągu ( myattr="hello"
) lub może być ciągiem interpolowanym AngularJS z osadzonymi wyrażeniami ( myattr="my_{{helloText}}"
). Potraktuj to jako „jednokierunkową” komunikację z zakresu nadrzędnego do dyrektywy podrzędnej. John Lindquist ma serię krótkich screencastów wyjaśniających każdy z nich. Screencast na @ jest tutaj: https://egghead.io/lessons/angularjs-isolate-scope-attribute-binding
&
pozwala zakresowi izolowanemu dyrektywy przekazywać wartości do zakresu nadrzędnego w celu oceny w wyrażeniu zdefiniowanym w atrybucie. Zauważ, że atrybut dyrektywy jest domyślnie wyrażeniem i nie używa składni wyrażenia nawiasów klamrowych. Ten trudniej jest wyjaśnić w tekście. Screencast na temat & jest tutaj: https://egghead.io/lessons/angularjs-isolate-scope-expression-binding
=
ustanawia dwukierunkowe wiążące wyrażenie między zakresem izolowania dyrektywy a zakresem nadrzędnym. Zmiany w zakresie potomnym są propagowane do elementu nadrzędnego i odwrotnie. Pomyśl o = jako kombinacji @ i &. Screencast on = is here: https://egghead.io/lessons/angularjs-isolate-scope-two-way-binding
I w końcu tutaj jest screencast, który pokazuje wszystkie trzy użyte razem w jednym widoku: https://egghead.io/lessons/angularjs-isolate-scope-review
Chciałbym wyjaśnić pojęcia z perspektywy dziedziczenia prototypów JavaScript. Mam nadzieję, że pomogą zrozumieć.
Istnieją trzy opcje definiowania zakresu dyrektywy:
scope: false
: Domyślne kątowe. Zakres dyrektywy jest dokładnie taki, jak jej zakres nadrzędny ( parentScope
).scope: true
: Angular tworzy zakres dla tej dyrektywy. Zakres prototypowo dziedziczy parentScope
.scope: {...}
: zakres izolowany wyjaśniono poniżej. Określenie scope: {...}
definiuje isolatedScope
. isolatedScope
Nie dziedziczy właściwości z parentScope
, choć isolatedScope.$parent === parentScope
. Jest definiowany poprzez:
app.directive("myDirective", function() {
return {
scope: {
... // defining scope means that 'no inheritance from parent'.
},
}
})
isolatedScope
nie ma bezpośredniego dostępu do parentScope
. Ale czasami dyrektywa musi się komunikować z parentScope
. Komunikują się za pośrednictwem @
, =
i &
. Wątek o używaniu symboli @
, =
a &
mówimy o scenariuszach wykorzystującychisolatedScope
.
Zwykle jest używany do niektórych popularnych komponentów współdzielonych przez różne strony, takich jak Modały. Izolowany zakres zapobiega zanieczyszczeniu zasięgu globalnego i jest łatwy do dzielenia się między stronami.
Oto podstawowa dyrektywa: http://jsfiddle.net/7t984sf9/5/ . Obraz do zilustrowania to:
@
: wiązanie w jedną stronę@
po prostu przekazuje właściwość od parentScope
do isolatedScope
. Nazywa się to one-way binding
, co oznacza, że nie można modyfikować wartości parentScope
właściwości. Jeśli znasz dziedziczenie JavaScript, możesz łatwo zrozumieć te dwa scenariusze:
Jeśli właściwość wiązania jest typem pierwotnym, tak jak interpolatedProp
w przykładzie: można zmodyfikować interpolatedProp
, ale parentProp1
nie można go zmienić. Jeśli jednak zmienisz wartość parentProp1
, interpolatedProp
zostanie ona zastąpiona nową wartością (gdy kątowy $ digest).
Jeśli właściwość powiązania jest jakimś obiektem, na przykład parentObj
: ponieważ ta, do której przekazano, isolatedScope
jest odwołaniem, modyfikacja wartości spowoduje wyzwolenie tego błędu:
TypeError: Cannot assign to read only property 'x' of {"x":1,"y":2}
=
: wiązanie dwustronne=
jest wywoływana two-way binding
, co oznacza, że każda modyfikacja w childScope
spowoduje również aktualizację wartości w parentScope
i odwrotnie. Ta reguła działa zarówno dla prymitywów, jak i obiektów. Jeśli zmienisz typ wiązania parentObj
na =
, przekonasz się, że możesz zmodyfikować wartość parentObj.x
. Typowym przykładem jest ngModel
.
&
: powiązanie funkcji&
pozwala dyrektywie na wywołanie jakiejś parentScope
funkcji i przekazanie pewnej wartości z dyrektywy. Na przykład sprawdź JSFiddle: & w zakresie dyrektywy .
Zdefiniuj klikalny szablon w dyrektywie, taki jak:
<div ng-click="vm.onCheck({valueFromDirective: vm.value + ' is from the directive'})">
I skorzystaj z dyrektywy jak:
<div my-checkbox value="vm.myValue" on-check="vm.myFunction(valueFromDirective)"></div>
Zmienna valueFromDirective
jest przekazywana z dyrektywy do kontrolera nadrzędnego przez {valueFromDirective: ...
.
Odniesienie: Zrozumienie zakresów
Nie moje skrzypce, ale http://jsfiddle.net/maxisam/QrCXh/ pokazuje różnicę. Kluczowym elementem jest:
scope:{
/* NOTE: Normally I would set my attributes and bindings
to be the same name but I wanted to delineate between
parent and isolated scope. */
isolatedAttributeFoo:'@attributeFoo',
isolatedBindingFoo:'=bindingFoo',
isolatedExpressionFoo:'&'
}
@ : wiązanie w jedną stronę
= : wiązanie dwukierunkowe
& : powiązanie funkcji
AngularJS - Lunety izolowane - @ vs = vs &
Krótkie przykłady z objaśnieniami są dostępne pod poniższym linkiem:
http://www.codeforeach.com/angularjs/angularjs-isolated-scopes-vs-vs
@ - wiążący w jedną stronę
W dyrektywie:
scope : { nameValue : "@name" }
Z uwagi:
<my-widget name="{{nameFromParentScope}}"></my-widget>
= - wiązanie dwukierunkowe
W dyrektywie:
scope : { nameValue : "=name" },
link : function(scope) {
scope.name = "Changing the value here will get reflected in parent scope value";
}
Z uwagi:
<my-widget name="{{nameFromParentScope}}"></my-widget>
& - Wywołanie funkcji
W dyrektywie:
scope : { nameChange : "&" }
link : function(scope) {
scope.nameChange({newName:"NameFromIsolaltedScope"});
}
Z uwagi:
<my-widget nameChange="onNameChange(newName)"></my-widget>
Zajęło mi naprawdę dużo czasu, aby naprawdę się z tym pogodzić. Kluczem do mnie było zrozumienie, że „@” dotyczy rzeczy, które chcesz ocenić in situ i które zostały przekazane do dyrektywy jako stała, gdzie „=” faktycznie przekazuje sam obiekt.
Jest ładny post na blogu, który wyjaśnia to na: http://blog.ramses.io/technical/AngularJS-the-difference-between-@-&-and-=-when-declaring-directives-using-isolate-scopes