Dyrektywa AngularJS – Zakresy
Zakresy w dyrektywach AngularJS
Zamierzam porozmawiać o dyrektywach AngularJS i różnych typach zakresów, które mogą być używane. Istnieją 3 główne sposoby, w jakie zakres może być przekazany do dyrektywy z widoku wywołującego (HTML):
- Default Scope
- Inherited Scope
- Isolated Scope
And the isolated scope could itself be:
- Oneway
- Twoway
- Method Reference
Default Scope
W tym typie zakres z widoku zewnętrznego po prostu wpływa do dyrektywy. Mówiąc inaczej, zakres jest przekazywany jako „referencja” do dyrektywy. Wszystkie dane z zakresu będą natychmiast dostępne w dyrektywie do wykorzystania. Podobnie, każda zmiana dokonana w zakresie w dyrektywie zostanie natychmiast odzwierciedlona w wywołującym ją widoku.
Osiąga się to poprzez określenie zakresu jako
scope: false // false is the default value
w definicji dyrektywy.
W poniższym przykładzie, 'nazwa’ wpływa do dyrektywy i każda dokonana zmiana jest natychmiast odzwierciedlana na zewnątrz. Ponieważ zakres jest ustawiony na true, dyrektywa dostaje zakres jako swój rozmówca. Teraz wszelkie zmiany wprowadzone do nazwy w dyrektywie będą natychmiast odzwierciedlone w kontrolerze 'MyController’.
var myApp = angular.module('myApp', );
myApp.controller('MyController', function($scope) {
$scope.name = "Jack";
});// usage: <div upper-case/></div>
myApp.directive('upperCase', function() {
return {
scope: false,
template: 'Name: <input ng-model="name"></input>'
}
});
Live fiddle is @ https://jsfiddle.net/madhanganesh/830rn1fm/
Inherited Scope
W tym typie nowy zakres jest dziedziczony z zakresu widoku. W Javascript, obiekty są dziedziczone przy użyciu dziedziczenia prototypowego. Ten scenariusz jest przedstawiony na poniższym diagramie:
Osiąga się to poprzez określenie zakresu jako
scope: true
w definicji dyrektywy.
W poniższym przykładzie możesz spróbować zmienić nazwę w dyrektywie. Ta zmiana nie zostanie odzwierciedlona na zewnątrz z powodu „dziedziczonego” zakresu. Wartość przepływa tylko wewnątrz, ale każda zmiana spowoduje kopię dla dyrektywy i nie zostanie odzwierciedlona na zewnątrz.
W poniższym przykładzie na żywo można zobaczyć, że 'nazwa’ przepływa do dyrektywy; ale zmiana dokonana w dyrektywie nie zostanie odzwierciedlona na zewnątrz.
W poniższym przykładzie zakres dyrektywy otrzymuje wartość true. Oznacza to, że dla dyrektywy tworzony jest zakres, który „dziedziczy” po zakresie kontrolera. Zgodnie z prototypowymi zasadami dziedziczenia javascript, obiekt pochodny (zakres dyrektywy) odwołuje się do tych samych właściwości obiektu nadrzędnego (zakres kontrolera). Wszelkie zmiany dokonane w kontrolerze będą odzwierciedlone w dyrektywie, aż do momentu, gdy zostanie zmieniona właściwość „name” w dyrektywie. W tym momencie tworzony jest nowy obiekt dla dyrektywy i zmiany są nieprzezroczyste względem siebie.
var myApp = angular.module('myApp', );
myApp.controller('MyController', function($scope) {
$scope.name = "Jack";
});// usage: <div upper-case/></div>
myApp.directive('upperCase', function() {
return {
scope: true,
template: 'Name: <input ng-model="name"></input>'
}
});
Live fiddle is @ https://jsfiddle.net/madhanganesh/57sb6yg8/
Isolated Scope
W tym typie definicji zakresu dyrektywa otrzymuje niezależny zakres, który nie otrzymuje ani nie odsyła żadnych danych do widoku zawierającego.
Osiąga się to przez określenie zakresu jako
scope: {}
w definicji dyrektywy.
W poniższym przykładzie izolowany zakres jest osiągnięty przez przekazanie pustego obiektu {} do dyrektywy.
var myApp = angular.module('myApp', );
myApp.controller('MyController', function($scope) {
$scope.name = "Jack";
});// usage: <div upper-case/></div>
myApp.directive('upperCase', function() {
return {
scope: {},
template: 'Name: <input ng-model="name"></input>'
}
});
Live fiddle is @ https://jsfiddle.net/madhanganesh/7d37w08e/
Isolated scope jest naprawdę więcej niż całkowite ograniczenie wszelkich danych, które mają być przekazywane do (i z) dyrektywy. Na jednym końcu spektrum można całkowicie ograniczyć dane, jak pokazano w powyższym przykładzie. Ale możliwe jest również przekazanie jednego lub więcej atrybutów do dyrektywy i przechwycenie ich jako zakresu dyrektywy. Elastyczność polega na sposobie, w jaki przekazywany atrybut jest interpretowany wewnątrz dyrektywy. Atrybut przekazany do dyrektywy może być interpretowany na jeden z 3 sposobów:
- jako jednokierunkowy, który jest obliczany przed przekazaniem do dyrektywy
- jako dwukierunkowy a referencja do właściwości w zakresie wywołania
- jako referencja do metody w zakresie wywołania
Expression
Wywołujący dyrektywę może jawnie przekazać wartość, jak pokazano poniżej:
<div my-directive name='{{name}}' />
// an expression is passed to the directive
Sposób, w jaki jest to uchwycone wewnątrz dyrektywy, to:
scope: {
name: '@name'
}
@ Symbol@ mówi angularowi, aby traktował atrybut name jako wyrażenie i oceniał je przed przypisaniem wartości do właściwości text. Ponieważ wyrażenie jest oceniane, jest to wiązanie jednokierunkowe i jakakolwiek aktualizacja wartości wewnątrz dyrektywy nie zostanie odzwierciedlona na zewnątrz.
W poniższym przykładzie, zobacz, że właściwość name jest przekazywana do dyrektywy. Jest to wyrażenie, które jest obliczane i przypisywane do izolowanego zakresu dyrektywy. Oznacza to, że wartość „Jack” jest oceniana i przypisywana jako tekst wewnątrz dyrektywy.
var myApp = angular.module('myApp', );
myApp.controller('MyController', function($scope) {
$scope.name = 'Jack';
});
// usage: <div my-directive name='{{name}}' />
myApp.directive('upperCase', function() {
return {
scope: {
name: '@name'
},
template: 'Name: <input ng-model="name"></input>'
}
});
Live fiddle to @ https://jsfiddle.net/madhanganesh/ybzcryt0/4/
Ponieważ nazwa jest tekstem w dyrektywie, zmiany są lokalne dla dyrektywy i nic nie jest współdzielone z kontrolerem nadrzędnym.
Two-way (odwołanie do właściwości)
Wywołujący dyrektywę może przekazać odwołanie do właściwości do dyrektywy, jak w:
<div my-directive name='data.name' />
// a property reference to the directive
Sposób w jaki jest to przechwytywane wewnątrz dyrektywy jest następujący:
scope: {
name: '=name'
}
= symbol mówi angularowi, aby traktował atrybut name jako odwołanie do konkretnej właściwości zakresu wywołania. Tak więc wartość jest przekazywana do dyrektywy i każda zmiana dokonana na atrybucie jest natychmiast odzwierciedlana na zewnątrz.
W poniższym przykładzie, zobacz, że właściwość name jest przekazywana do dyrektywy. Jest to odniesienie do właściwości name w zakresie rodzica.
var myApp = angular.module('myApp', );
myApp.controller('MyController', function($scope) {
$scope.name = 'Jack';
});
myApp.directive('upperCase', function() {
return {
scope: {
name: '=name'
},
template: 'Name: <input ng-model="name"></input>'
}
});
Live fiddle jest @ https://jsfiddle.net/madhanganesh/o74nvcj3/1/
Ponieważ nazwa jest odniesieniem do właściwości w kontrolerze wszelkie zmiany po obu stronach zostaną odzwierciedlone w obu.
Odniesienie do metody
Sposób, w jaki jest przekazywane z wywołania widoku jest:
<div my-directive nameFn="getName()" />
// a method reference is passed to the directive
Sposób, w jaki jest przechwytywane wewnątrz dyrektywy jest:
scope: {
nameFn: '& nameFn'
}
& Symbol mówi angularowi, aby traktował atrybut nameFn jako odniesienie do konkretnej metody zakresu wywołania. Ta metoda może być następnie wykonana z wnętrza dyrektywy, gdy jest to wymagane.
W poniższym przykładzie widać, że właściwość nameFn jest metodą, której referencja jest przekazywana wewnątrz dyrektywy. Ta funkcja jest wykonywana z poziomu dyrektywy, ale oceniana w kontekście zakresu wywołania.
var myApp = angular.module('myApp', );
myApp.controller('MyController', function($scope) {
$scope.name = 'Jack';
$scope.getName = function() {
return $scope.name;
}
});
myApp.directive('upperCase', function() {
return {
scope: {
nameCb: '&name'
},
//template: 'Name: <input ng-model="nameFn()"></input>'
template: 'Name: {{textCb()}}'
}
});
Live fiddle is @ https://jsfiddle.net/madhanganesh/6w4msr5k/1/
Podsumowanie
Jak widać zakres dyrektywy jest dość wyczerpujący, poniższe podsumowanie ujmuje możliwości i ich znaczenie.
- Default : Dyrektywa dostaje taki sam zakres jak jej widok zawierający
- Dziedziczone: Dyrektywa dostaje zakres, który jest dziedziczony z zakresu widoku zawierającego
- Isolated: Dyrektywa otrzymuje zakres niezależny od widoku zawierającego
W ramach zakresu izolowanego istnieją 3 możliwości:
Oneway : Atrybut dyrektywy jest traktowany jako wyrażenie i obliczany przed przypisaniem do konkretnej właściwości izolowanego zakresu dyrektywy
.