Dyrektywa AngularJS – Zakresy

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.

view and directive bound vis scope

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

.