AngularJS-direktiv – scope

Jag har för avsikt att tala om AngularJS-direktiv och olika typer av scope som kan användas. Det finns 3 huvudsakliga sätt på vilka scope kan skickas till direktivet från den åberopande vyn (HTML):

  • Default Scope
  • Inherited Scope
  • Isolated Scope

Och det isolerade scope kan i sig självt vara:

  • Oneway
  • Twoway
  • Method Reference

Default Scope

I den här typen flyter räckvidden från den yttre vyn bara in i direktivet. Med andra ord skickas räckvidden som ”referens” till direktivet. Alla data från räckvidden kommer omedelbart att vara tillgängliga för konsumtion i direktivet. På samma sätt kommer alla ändringar som görs i räckvidden i direktivet att återspeglas omedelbart i den åberopande vyn.

vyn och direktivet är bundna till räckvidden

Detta uppnås genom att man specificerar räckvidden som

scope: false // false is the default value

i direktivdefinitionen.

I exemplet nedan flygs ”name” in i direktivet och alla ändringar som görs återspeglas omedelbart utanför. Eftersom scope är satt till true får direktivet scope som sin anropare. Nu reflekteras alla ändringar som görs i ”name” i direktivet omedelbart i kontrollern ”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 den här typen ärvs ett nytt scope från view scope. I Javascript ärvs objekt med hjälp av prototypisk nedärvning. Detta scenario visas i diagrammet nedan:

Detta uppnås genom att ange scope som

scope: true

i direktivdefinitionen.

I exemplet nedan kan du prova att ändra namnet i direktivet. Den här ändringen kommer inte att reflekteras utanför på grund av det ”nedärvda” tillämpningsområdet. Värdet flyter bara inåt men varje ändring kommer att resultera i en kopia för direktivet och kommer inte att reflekteras utåt.

I det levande exemplet nedan kan du se att ”name” flyter in i direktivet; men ändring som görs i direktivet kommer inte att reflekteras utåt.

I exemplet nedan har direktivets räckvidd givits ett värde av true. Detta innebär att ett scope skapas för direktivet som ”ärver” från controllerns scope. Enligt de prototypiska arvsreglerna i JavaScript hänvisar det härledda objektet (direktivets scope) till samma egenskaper som det överordnade objektet (controllerns scope). Alla ändringar som görs i kontrollanten kommer att återspeglas i direktivet, tills en ändring görs i egenskapen ”name” i direktivet. Då skapas ett nytt objekt för direktivet och ändringarna är ogenomskinliga för varandra.

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 denna typ av räckviddsdefinition får direktivet ett oberoende räckvidd som inte tar emot eller skickar tillbaka några data till den innehållande vyn.

Detta uppnås genom att ange scope som

scope: {}

i direktivdefinitionen.

I exemplet nedan uppnås isolerad räckvidd genom att ett tomt objekt {} överförs till 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/

Isolerad räckvidd är egentligen mer än att helt och hållet begränsa all data som ska överföras till (och från) direktivet. I ena änden av spektrumet kan du helt begränsa data som visas i exemplet ovan. Men det är möjligt att skicka ett eller flera attribut till direktivet och fånga dem som ett scope för direktivet. Flexibiliteten ligger i hur det överlämnade attributet tolkas i direktivet. Det attribut som överlämnats till direktivet kan tolkas på ett av de tre följande sätten:

  • som ett envägsattribut som utvärderas innan det överlämnats till direktivet
  • som ett tvåvägsattribut som en referens till en egenskap i det anropande tillämpningsområdet
  • som en referens till en metod i det anropande tillämpningsområdet

Uttryck

Direktivets anropare kan uttryckligen överlåta ett värde som visas nedan:

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

Sättet det fångas i direktivet är:

scope: {
name: '@name'
}

@-symbolen talar om för angular att betrakta attributet name som ett uttryck och utvärdera det innan värdet tilldelas textegenskapen. Eftersom uttrycket utvärderas är det en envägsbindning och alla uppdateringar av värdet i direktivet kommer inte att reflekteras utanför.

I exemplet nedan ser du att name-egenskapen överförs till direktivet. Detta är ett uttryck som utvärderas och tilldelas direktivets isolerade scope. Det betyder att värdet ”Jack” utvärderas och tilldelas som text inuti 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 is @ https://jsfiddle.net/madhanganesh/ybzcryt0/4/

Eftersom name är en text i direktivet är ändringarna lokala för direktivet och inget delas med den överordnade styrenheten.

Tvåvägs (referens till egenskap)

Direktivets anropare kan skicka en referens till en egenskap till direktivet, som i:

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

Sättet som fångas inne i direktivet är:

scope: {
name: '=name'
}

=-symbolen talar om för angular att betrakta attributet name som en referens till en specifik egenskap i det anropande scope. Så värdet skickas in i direktivet och varje ändring som görs på attributet reflekteras omedelbart utanför.

I exemplet nedan ser du att name-egenskapen skickas till direktivet. Detta är en referens till name-egenskapen i det överordnade 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 is @ https://jsfiddle.net/madhanganesh/o74nvcj3/1/

Om name är en referens till egendomen i controllern kommer alla ändringar på endera sidan att reflekteras till båda.

Referens till metod

Sättet det överförs från anropande vy är:

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

Sättet det fångas inne i direktivet är:

scope: {
nameFn: '& nameFn'
}

& symbolen talar om för angular att betrakta nameFn-attributet som en referens till specifik metod i anropande scope. Denna metod kan sedan exekveras från direktivet när så krävs.

I exemplet nedan kan du se att nameFn-egenskapen är en metod vars referens skickas in i direktivet. Denna funktion exekveras från direktivet men utvärderas i kontexten för det anropande scope.

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 är direktivs scope ganska uttömmande, nedanstående sammanfattning fångar möjligheterna och deras innebörd.

  • Default : Directive gets the same scope as its containing view
  • Inherited: Direktiv får en räckvidd som ärvs från räckvidden för den innehållande vyn
  • Isolerad: Direktiv får en räckvidd som ärvs från räckvidden för den innehållande vyn
  • : Direktiv får ett tillämpningsområde som är oberoende av den innehållande vyn

Och inom det isolerade tillämpningsområdet finns det tre möjligheter:

Oneway : Direktivattributet betraktas som ett uttryck och utvärderas innan det tilldelas en specifik egenskap i direktivets isolerade tillämpningsområde