Ответы:
@
позволяет передать значение, определенное в атрибуте директивы, в область изоляции директивы. Значением может быть простое строковое значение ( myattr="hello"
) или строка с интерполяцией AngularJS со встроенными выражениями ( myattr="my_{{helloText}}"
). Думайте об этом как об односторонней связи из родительской области в дочернюю директиву. У Джона Линдквиста есть серия коротких скринкастов, объясняющих каждый из них. Скринкаст на @ здесь: https://egghead.io/lessons/angularjs-isolate-scope-attribute-binding
&
позволяет изолированной области действия директивы передавать значения в родительскую область для оценки в выражении, определенном в атрибуте. Обратите внимание, что атрибут directive является неявным выражением и не использует синтаксис выражения с двойными фигурными скобками. Это сложнее объяснить в тексте. Скринкаст на & находится здесь: https://egghead.io/lessons/angularjs-isolate-scope-expression-binding
=
устанавливает двустороннее выражение привязки между изолирующей областью директивы и родительской областью. Изменения в дочерней области распространяются на родительский и наоборот. Думайте о = как о комбинации @ и &. Скриншот на = здесь: https://egghead.io/lessons/angularjs-isolate-scope-two-way-binding
И, наконец, вот скриншот, который показывает все три, использованные вместе в одном представлении: https://egghead.io/lessons/angularjs-isolate-scope-review
Я хотел бы объяснить концепции с точки зрения наследования прототипов JavaScript. Надеюсь, поможет понять.
Существует три варианта определения области действия директивы:
scope: false
: Угловой по умолчанию. Область действия директивы в точности совпадает с областью действия родительской области ( parentScope
).scope: true
: Angular создает область действия для этой директивы. Область действия прототипно наследуется от parentScope
.scope: {...}
Изолированная сфера объясняется ниже. Указание scope: {...}
определяет isolatedScope
. An isolatedScope
не наследует свойства от parentScope
, хотя isolatedScope.$parent === parentScope
. Это определяется через:
app.directive("myDirective", function() {
return {
scope: {
... // defining scope means that 'no inheritance from parent'.
},
}
})
isolatedScope
не имеет прямого доступа к parentScope
. Но иногда директиве необходимо общаться с parentScope
. Они общаются через @
, =
и &
. Тема об использовании символов @
, =
и &
речь идет о сценариях использованияisolatedScope
.
Обычно он используется для некоторых общих компонентов, используемых разными страницами, таких как модалы. Изолированная область предотвращает загрязнение глобальной области и легко распределяется между страницами.
Вот основная директива: http://jsfiddle.net/7t984sf9/5/ . Изображение для иллюстрации:
@
: односторонняя привязка@
просто передает свойство из parentScope
в isolatedScope
. Это называется one-way binding
, что означает, что вы не можете изменить значение parentScope
свойств. Если вы знакомы с наследованием JavaScript, вы можете легко понять эти два сценария:
Если свойство привязки является примитивным типом, как interpolatedProp
в примере: вы можете изменить interpolatedProp
, но parentProp1
не изменится. Однако, если вы измените значение parentProp1
, interpolatedProp
будет перезаписано новым значением (когда angular $ digest).
Если свойство привязки - это какой-то объект, например parentObj
: так как переданный объект isolatedScope
является ссылкой, изменение значения вызовет эту ошибку:
TypeError: Cannot assign to read only property 'x' of {"x":1,"y":2}
=
: двусторонняя привязка=
называется two-way binding
, что означает, что любая модификация в childScope
будет также обновлять значение в parentScope
, и наоборот. Это правило работает как для примитивов, так и для объектов. Если вы измените тип привязки parentObj
на be =
, вы обнаружите, что можете изменить значение parentObj.x
. Типичный пример ngModel
.
&
: привязка функции&
позволяет директиве вызывать некоторую parentScope
функцию и передавать ей значение из директивы. Например, проверьте JSFiddle: & в области действия директивы .
Определите интерактивный шаблон в директиве, например:
<div ng-click="vm.onCheck({valueFromDirective: vm.value + ' is from the directive'})">
И используйте директиву как:
<div my-checkbox value="vm.myValue" on-check="vm.myFunction(valueFromDirective)"></div>
Переменная valueFromDirective
передается из директивы в родительский контроллер через {valueFromDirective: ...
.
Ссылка: Понимание областей
Не моя скрипка, но http://jsfiddle.net/maxisam/QrCXh/ показывает разницу. Ключевая часть:
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:'&'
}
@ : односторонняя привязка
= : двусторонняя привязка
& : привязка функции
AngularJS - изолированные области видимости - @ vs = vs &
Короткие примеры с пояснениями доступны по ссылке ниже:
http://www.codeforeach.com/angularjs/angularjs-isolated-scopes-vs-vs
@ - односторонняя привязка
В директиве:
scope : { nameValue : "@name" }
Ввиду:
<my-widget name="{{nameFromParentScope}}"></my-widget>
= - двусторонняя привязка
В директиве:
scope : { nameValue : "=name" },
link : function(scope) {
scope.name = "Changing the value here will get reflected in parent scope value";
}
Ввиду:
<my-widget name="{{nameFromParentScope}}"></my-widget>
& - вызов функции
В директиве:
scope : { nameChange : "&" }
link : function(scope) {
scope.nameChange({newName:"NameFromIsolaltedScope"});
}
Ввиду:
<my-widget nameChange="onNameChange(newName)"></my-widget>
Мне потребовалось очень много времени, чтобы действительно разобраться с этим. Ключом для меня было понимание того, что «@» относится к вещам, которые вы хотите оценить in situ и передать в директиву как константу, где «=» фактически пропускает сам объект.
Есть хороший пост в блоге, который объясняет это по этому адресу: http://blog.ramses.io/technical/AngularJS-the-difference-between-@-&-and-=-when-declaring-directives-using-isolate-scopes