AngularJS-direktiver – Scopes

Jeg har til hensigt at tale om AngularJS-direktiver og forskellige typer af scopes, der kan bruges. Der er 3 hovedmåder, hvorpå scope kan overføres til direktivet fra den påberåbende visning (HTML):

  • Default Scope
  • Inherited Scope
  • Isolated Scope

Og det isolerede scope kunne i sig selv være:

  • Oneway
  • Twoway
  • Method Reference

Default Scope

I denne type flyder scope fra den ydre visning bare ind i direktivet. Med andre ord overføres omfanget som “reference” til direktivet. Alle scope-data vil være umiddelbart tilgængelige i direktivet til forbrug. Ligeledes vil enhver ændring af omfanget i direktivet straks blive afspejlet i den anråbende visning.

visningen og direktivet er bundet vis scope

Dette opnås ved at specificere omfanget som

scope: false // false is the default value

i direktivdefinitionen.

I nedenstående eksempel er “name” fløjet ind i direktivet, og enhver ændring, der foretages, afspejles straks udenfor. Fordi scope er sat sandt, får direktivet scope som sin opkalder. Nu vil enhver ændring af navnet i direktivet straks blive afspejlet i controlleren ‘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

I denne type arves et nyt scope fra view-scope. I Javascript arves objekter ved hjælp af prototypisk arv. Disse scenarier er afbildet i diagrammet nedenfor:

Dette opnås ved at specificere scope som

scope: true

i direktivdefinitionen.

I eksemplet nedenfor kan du prøve at ændre navnet i direktivet. Denne ændring vil ikke blive afspejlet udenfor på grund af “nedarvet” scope. Værdien flyder kun indenfor, men enhver ændring vil resultere i en kopi for direktivet og vil ikke blive reflekteret udenfor.

I det levende eksempel nedenfor kan du se, at ‘name’ flyder ind i direktivet; men ændring foretaget i direktivet vil ikke blive reflekteret udenfor.

I eksemplet nedenfor er direktivets anvendelsesområde givet en værdi på true. Det betyder, at der oprettes et scope for direktivet, som “arver” fra controllerens scope. I henhold til de prototypiske arveregler i javascript henviser det afledte objekt (direktivets scope) til de samme egenskaber som det overordnede objekt (controllerens scope). Alle ændringer, der foretages i controlleren, vil blive afspejlet i direktivet, indtil der foretages en ændring i “name”-egenskaben i direktivet. På det tidspunkt oprettes der et nyt objekt for direktivet, og ændringerne er uigennemsigtige for hinanden.

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

I denne type scope-definition får direktivet et uafhængigt scope, som ikke modtager eller sender data tilbage til den indeholdende visning.

Dette opnås ved at specificere scope som

scope: {}

i direktivdefinitionen.

I eksemplet nedenfor opnås isolated scope ved at sende et tomt objekt {} til direktivet.

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 er i virkeligheden mere end en fuldstændig begrænsning af alle data, der skal sendes ind (og ud) af et direktiv. I den ene ende af spektret kan du fuldstændig begrænse dataene som vist i ovenstående eksempel. Men det er muligt at videregive en eller flere attributter til direktivet og fange dem som et anvendelsesområde for direktivet. Fleksibiliteten ligger i den måde, hvorpå den overførte attribut fortolkes i direktivet. Attributten, der overgives til direktivet, kan fortolkes på en af de 3 måder:

  • som en oneway, der bliver evalueret, før den overgives til direktivet
  • som en twoway en reference til egenskab i kaldende scope
  • som en reference til metode i kaldende scope

Udtryk

Den, der kalder direktivet, kan eksplicit overgive en værdi som vist nedenfor:

<div my-directive name='{{name}}' />
// an expression is passed to the directive

Den måde, det er fanget inde i direktivet, er:

scope: {
name: '@name'
}

@-symbolet fortæller angular at betragte name-attributten som et udtryk og evaluere den, før værdien tildeles tekstegenskaben. Fordi udtrykket evalueres, er det en envejsbinding, og enhver opdatering af værdien inden for direktivet vil ikke blive afspejlet udenfor.

I eksemplet nedenfor kan du se, at name-egenskaben overføres til direktivet. Dette er et udtryk, der evalueres og tildeles til direktivets isolerede anvendelsesområde. Det betyder, at værdien “Jack” evalueres og tildeles som tekst inde i direktivet.

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 er @ https://jsfiddle.net/madhanganesh/ybzcryt0/4/

Da name er en tekst i direktivet, er ændringerne lokale for direktivet, og der deles ikke noget med den overordnede controller.

Tovejs (reference til egenskab)

Direktivets opkalder kan videregive en reference til en egenskab til direktivet, som i:

<div my-directive name='data.name' />
// a property reference to the directive

Måden, hvorpå det opfanges inde i direktivet, er:

scope: {
name: '=name'
}

=-symbolet fortæller angular, at attributten name skal betragtes som en reference til en specifik egenskab i det kaldende scope. Så værdien overføres til direktivet, og enhver ændring, der foretages på attributten, afspejles udenfor med det samme.

I eksemplet nedenfor kan du se, at name-egenskaben overføres til direktivet. Dette er en reference til name-egenskaben i overordnet scope.

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 er @ https://jsfiddle.net/madhanganesh/o74nvcj3/1/

Da name er en reference til egenskaben i controller, vil eventuelle ændringer på begge sider blive afspejlet i begge.

Reference til metode

Måden, den overføres fra kaldende visning, er:

<div my-directive nameFn="getName()" />
// a method reference is passed to the directive

Måden, den opfanges inde i direktivet, er:

scope: {
nameFn: '& nameFn'
}

& symbolet fortæller angular at betragte nameFn-attributten som en reference til en specifik metode i kaldende anvendelsesområde. Denne metode kan derefter udføres inde fra direktivet, når det er nødvendigt.

I eksemplet nedenfor kan du se, at nameFn-egenskaben er en metode, hvis reference overføres inde i direktivet. Denne funktion udføres fra direktivet, men evalueres i konteksten for det kaldende anvendelsesområde.

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/

Summary

Som du kan se, er direktivets anvendelsesområde ret udtømmende, nedenstående resumé indfanger mulighederne og deres betydning.

  • Default : Direktivet får samme anvendelsesområde som det indeholdende view
  • Inherited: Direktiv får et omfang, der er arvet fra omfanget af den indeholdende visning
  • Isoleret: Direktiv får et anvendelsesområde, der er uafhængigt af den indeholdende visning

Og inden for isoleret anvendelsesområde er der 3 muligheder:

Oneway : Direktivattributten betragtes som et udtryk og evalueres, før den tildeles til en specifik egenskab i direktivets isolerede anvendelsesområde