AngularJS: Различия между = & @ в области действия директивы?
Создание изолированной области видимости внутри директивы позволяет нам сопоставить внешнюю область видимости с внутренней областью видимости. Мы видели шесть разных способов сопоставления с атрибутами:
- = атр
- & атр
- @attr
- знак равно
- &
- @
Что делает каждый из этих вариантов отображения области?
2 ответа
Это может сбивать с толку, но, надеюсь, простой пример прояснит это. Во-первых, давайте отделим привязки модели от поведения.
Вот скрипка, которая должна помочь связать вещи вместе: http://jsfiddle.net/jeremylikness/3pvte/
И объяснил... если ваша директива выглядит так:
<my-directive target="foo"/>
Тогда у вас есть эти возможности для области:
{ target : '=' }
Это свяжет scope.target (директива) с $scope.foo (внешняя область действия). Это потому, что = для двусторонней привязки, и когда вы ничего не указываете, он автоматически сопоставляет имя во внутренней области с именем атрибута в директиве. Изменения в scope.target обновят $scope.foo.
{ bar : '=target' }
Это свяжет scope.bar с $scope.foo. Это потому, что мы снова указываем двустороннее связывание, но говорим директиве, что то, что находится в атрибуте "target", должно отображаться во внутренней области видимости как "bar". Изменения в scope.bar обновят $scope.foo.
{ target : '@' }
Это установит для scope.target значение "foo", потому что @ означает "воспринимать буквально". Изменения в scope.target не будут распространяться за пределы вашей директивы.
{ bar : '@target' }
Это установит для scope.bar значение "foo", потому что @ берет его значение из целевого атрибута. Изменения в scope.bar не будут распространяться за пределы вашей директивы.
Теперь поговорим о поведении. Давайте предположим, что ваша внешняя область имеет это:
$scope.foo = function(parm1, parm2) { console.log(parm1 + ": " + parm2); }
Есть несколько способов получить к нему доступ. Если ваш HTML это:
<my-directive target='foo'>
затем
{ target : '=' }
Позволит вам вызвать scope.target(1,2) из вашей директивы.
То же самое,
{ bar : '=target' }
Позволяет вам вызывать scope.bar(1,2) из вашей директивы.
Более распространенный способ - установить это как поведение. Технически, амперсанд оценивает выражение в контексте родителя. Это важно Так что я мог бы иметь:
<my-directive target="a+b" />
И если родительская область имеет $scope.a = 1 и $scope.b = 2, то по моей директиве:
{ target: '&' }
Я могу вызвать scope.target(), и результат будет 3. Это важно - привязка предоставляется как функция для внутренней области, но директива может привязываться к выражению.
Более распространенный способ сделать это:
<my-directive target="foo(val1,val2)">
Тогда вы можете использовать:
{ target: '&' }
И позвоните из директивы:
scope.target({val1: 1, val2: 2});
Он берет переданный вами объект, сопоставляет свойства с параметрами в вычисляемом выражении, а затем вызывает поведение, в этом случае вызывается $scope.foo(1,2);
Вы также можете сделать это:
<my-directive target="foo(1, val)"/>
Это фиксирует первый параметр в литерале 1 и в директиве:
{ bar: '&target' }
Затем:
scope.bar(5)
Который вызвал бы $scope.foo(1,5);
Резюме
- @attr связывается с оцененным строковым значением соответствующего атрибута DOM.
- = attr связывается со свойством области видимости соответствующего атрибута DOM.
- & attr связывает с областью действия соответствующего атрибута DOM.
- @
- знак равно
- &
Мы используем 4, 5 и 6, если имя целевого атрибута DOM совпадает с именем proproty изолированной области видимости. Вот рабочая скрипка следующего примера.
Html
<div ng-app='isolate'>
<h3>Outer Scope</h3>
<input type="text" ng-model="myModel" />
<p>msg: {{ msg }}</p>
<h3>Inner Scope</h3>
<div id="inner">
<div my-directive at="{{ myModel }}" equals="myModel" ampersand="msg=msg+'click'"></div>
</div>
</div>
Javascript
angular.module('isolate', [])
.directive('myDirective', function () {
return {
template:
'<label>@attr</label><input value="{{ myAt }}" />' +
'<label>@</label><input value="{{ at }}" />' +
'<label>=attr</label><input ng-model="myEquals" />' +
'<label>=</label><input ng-model="equals" />' +
'<label>&attr</label><input type="button" ng-click="myAmpersand()" value="Btn" />' +
'<label>&</label><input type="button" ng-click="ampersand()" value="Btn" />',
scope: {
myAt: '@at',
myEquals: '=equals',
myAmpersand: '&ersand',
at: '@',
equals: '=',
ampersand: '&'
}
};
});