В чем разница между "@" и "=" в области действия в AngularJS?
Я внимательно прочитал документацию AngularJS по этой теме, а затем попробовал директиву. Здесь fiddle.
И вот некоторые соответствующие фрагменты:
-
Из HTML:
<pane bi-title="title" title="{{title}}">{{text}}</pane>
-
В директиве панели:
scope: { biTitle: '=', title: '@', bar: '=' },
Есть несколько вещей, которые я не получаю:
- Почему мне нужно использовать
"{{title}}"
с '@'
и "title"
с помощью '='
?
- Могу ли я получить доступ к родительской области напрямую, не украсив свой элемент атрибутом?
- В документации говорится: "Часто желательно передавать данные из изолированной области с помощью выражения и в родительскую область", но это, похоже, отлично работает с двунаправленным связыванием. Почему лучше использовать маршрут выражения?
Я нашел еще одну скрипту, которая также показывает выражение: http://jsfiddle.net/maxisam/QrCXh/
Ответы
Ответ 1
Почему мне нужно использовать "{{title}}" с " @" и "title" с помощью "="?
@ связывает свойство области локального/директивы с оцененным значением атрибута DOM. Если вы используете title=title1
или title="title1"
, значение атрибута DOM "title" - это просто строка title1
. Если вы используете title="{{title}}"
, значение атрибута DOM "title" - это интерполированное значение {{title}}
, поэтому строка будет иметь значение, на которое в настоящее время установлено свойство "title" родительской области. Поскольку значения атрибутов всегда являются строками, вы всегда будете иметь строковое значение для этого свойства в области директивы при использовании @.
= привязывает свойство области локальных/директивных объектов к свойствам родительской области. Таким образом, с = вы используете имя родительской модели/области видимости как значение атрибута DOM. Вы не можете использовать {{}}
с =.
С помощью @вы можете делать такие вещи, как title="{{title}} and then some"
- {{title}}, затем строка "и их некоторые" объединяется с ней. Конечная конкатенированная строка - это свойство локальной/директивы scope. (Вы не можете сделать это с помощью =, только @.)
С @ вам нужно будет использовать attr.$observe('title', function(value) { ... })
, если вам нужно использовать значение в вашей функции связи (ing). Например, if(scope.title == "...")
не будет работать так, как вы ожидаете. Обратите внимание, что это означает, что вы можете получить доступ к этому атрибуту асинхронно.
Вам не нужно использовать $observ(), если вы используете только значение в шаблоне. Например, template: '<div>{{title}}</div>'
.
С = вам не нужно использовать $observ.
Можно ли также напрямую обращаться к родительской области, не украсив мой элемент атрибутом?
Да, но только если вы не используете область изоляции. Удалите эту строку из своей директивы
scope: { ... }
а затем ваша директива не создаст новую область. Он будет использовать родительскую область. Затем вы можете напрямую получить доступ ко всем свойствам родительской области.
В документации говорится: "Часто желательно передавать данные из изолированной области видимости через выражение и в родительскую область", но это, похоже, отлично работает с двунаправленным связыванием. Почему лучше использовать маршрут выражения?
Да, двунаправленная привязка позволяет области локального/директива и родительской области обмениваться данными. "Связывание выражений" позволяет директиве вызывать выражение (или функцию), определяемое атрибутом DOM, - и вы также можете передавать данные в качестве аргументов выражения или функции. Таким образом, если вам не нужно обмениваться данными с родителем, вы просто хотите вызвать функцию, определенную в родительской области - вы можете использовать синтаксис и.
См. также
Ответ 2
Здесь есть много отличных ответов, но я хотел бы предложить свою точку зрения о различиях между привязками @
, =
и &
, которые оказались полезными для меня.
Все три привязки - это способы передачи данных из родительской области в вашу выделенную область директивы через атрибуты элемента:
-
@ привязка для передачи строк. Эти строки поддерживают выражения {{}}
для интерполированных значений. Например: , Интерполированное выражение оценивается против директивной родительской области.
-
= привязка предназначена для привязки двухсторонней модели. Модель в родительском пространстве связан с моделью в изолированной области действия. Изменения в одна модель влияет на другую, и наоборот.
-
& привязка предназначена для передачи метода в область вашей директивы, чтобы его можно вызвать в вашей директиве. Метод предварительно привязан к директивной родительской области и поддерживает аргументы. Например, если метод hello (name) в родительской области, то в чтобы выполнить метод изнутри вашей директивы, вы должны вызов $scope.hello({name: 'world'})
Я нахожу, что легче запомнить эти различия, обратившись к привязкам к области с помощью более короткого описания:
-
@
Связывание строки атрибута
-
=
Двусторонняя привязка модели
-
&
привязка метода обратного вызова
Символы также уточняют, что представляет собой переменная области видимости внутри вашей директивной реализации:
-
@
строка
-
=
модель
-
&
метод
В порядке полезности (для меня в любом случае):
Ответ 3
=
означает двунаправленное связывание, поэтому ссылка на переменную на родительскую область. Это означает, что при изменении переменной в директиве она также будет изменена в родительской области.
@
означает, что переменная будет скопирована (клонирована) в директиву.
Насколько я знаю, <pane bi-title="{{title}}" title="{{title}}">{{text}}</pane>
тоже должен работать. bi-title
получит значение переменной родительского объекта, которое может быть изменено в директиве.
Если вам нужно изменить несколько переменных в родительской области, вы можете выполнить функцию в родительской области из директивы (или передать данные через службу).
Ответ 4
Если вы хотите увидеть больше, как это работает с живым примером. http://jsfiddle.net/juanmendez/k6chmnch/
var app = angular.module('app', []);
app.controller("myController", function ($scope) {
$scope.title = "binding";
});
app.directive("jmFind", function () {
return {
replace: true,
restrict: 'C',
transclude: true,
scope: {
title1: "=",
title2: "@"
},
template: "<div><p>{{title1}} {{title2}}</p></div>"
};
});
Ответ 5
@
получить как строку
- Это не создает никаких привязок. Вы просто получаете слово, которое вы передали в виде строки
=
2-сторонняя привязка
- изменения, внесенные с контроллера, будут отражены в ссылке, содержащейся в директиве, и наоборот
&
Это ведет себя по-другому, потому что область получает функцию, которая возвращает объект, который был передан в. Я предполагаю, что это необходимо, чтобы заставить его работать. Эта скрипка должна быть понятной.
- После вызова этой функции getter результирующий объект ведет себя следующим образом:
- если функция была передана: тогда функция выполняется в закрытии родителя (контроллера) при вызове
- если была передана нефункция: просто получите локальную копию объекта, у которого нет привязок
Эта скрипка должна продемонстрировать, как они работают. Обратите особое внимание на функции области с get...
в названии, чтобы, надеюсь, лучше понять, что я имею в виду &
Ответ 6
В директиве можно добавить три способа:
- Родительский охват: это наследование по умолчанию.
Директива и ее родительская (контроллер/директива, внутри которой она лежит) обладают одинаковыми свойствами. Поэтому любые изменения, внесенные в переменные области внутри директивы, также отражаются в родительском контроллере. Вам не нужно указывать это значение по умолчанию.
- Директива Child scope: direct создает дочернюю область, которая наследуется от родительской области, если вы укажете переменную scope директивы как true.
Здесь, если вы измените переменные области видимости внутри директивы, она не будет отображаться в родительской области, но если вы измените свойство переменной области видимости, которое отражается в родительской области, так как вы фактически изменили переменную области действия родительской,
Пример,
app.directive("myDirective", function(){
return {
restrict: "EA",
scope: true,
link: function(element, scope, attrs){
scope.somvar = "new value"; //doesnot reflect in the parent scope
scope.someObj.someProp = "new value"; //reflects as someObj is of parent, we modified that but did not override.
}
};
});
- Изолированная область: это используется, когда вы хотите создать область, которая не наследуется от области контроллера.
Это происходит, когда вы создаете плагины, поскольку это делает директиву универсальной, поскольку она может быть помещена в любой HTML-код и не зависит от ее родительской области.
Теперь, если вы не хотите никакого взаимодействия с родительской областью, вы можете просто указать область как пустой объект. как,
scope: {} //this does not interact with the parent scope in any way
В основном это не так, поскольку нам нужно некоторое взаимодействие с родительской областью, поэтому мы хотим, чтобы некоторые из значений/изменений проходили. По этой причине мы используем:
1. "@" ( Text binding / one-way binding )
2. "=" ( Direct model binding / two-way binding )
3. "&" ( Behaviour binding / Method binding )
@ означает, что изменения в области контроллера будут отражены в области директивы, но если вы измените значение в области директивы, переменная области контроллера не будет затронута.
@всегда ожидает, что отображаемый атрибут будет выражением. Это очень важно; потому что для работы префикса "@" нам нужно обернуть значение атрибута внутри {{}}.
= является двунаправленным, поэтому, если вы изменяете переменную в области директивы, изменяется и переменная области контроллера
& используется для привязки метода области управления, так что при необходимости мы можем вызвать его из директивы
Преимущество здесь состоит в том, что имя переменной не должно быть одинаковым в области контроллера и области действия.
Например, область действия директивы имеет переменную "dirVar", которая синхронизируется с переменной "contVar" области управления. Это дает большую мощность и обобщение директивы, поскольку один контроллер может синхронизироваться с переменной v1, в то время как другой контроллер, использующий ту же директиву, может запрашивать dirVar для синхронизации с переменной v2.
Ниже приведен пример использования:
Директива и контроллер:
var app = angular.module("app", []);
app.controller("MainCtrl", function( $scope ){
$scope.name = "Harry";
$scope.color = "#333333";
$scope.reverseName = function(){
$scope.name = $scope.name.split("").reverse().join("");
};
$scope.randomColor = function(){
$scope.color = '#'+Math.floor(Math.random()*16777215).toString(16);
};
});
app.directive("myDirective", function(){
return {
restrict: "EA",
scope: {
name: "@",
color: "=",
reverse: "&"
},
link: function(element, scope, attrs){
//do something like
$scope.reverse();
//calling the controllers function
}
};
});
И html (обратите внимание на differnce для @и =):
<div my-directive
class="directive"
name="{{name}}"
reverse="reverseName()"
color="color" >
</div>
Вот ссылка на блог, который описывает это красиво.
Ответ 7
Просто мы можем использовать: -
-
@: - для значений String для одного способа привязки данных. в одном случае привязка данных вы можете передать значение области только директиве
-
=: - для значения объекта для двусторонней привязки данных. в двухстороннем связывании данных вы можете изменить значение области как в директиве, так и в html.
-
&: - для методов и функций.
ИЗМЕНИТЬ
В нашем определении Компонент для Angular версии 1.5 И выше
существует четыре разных типа привязок:
-
=
Двусторонняя привязка данных: - если мы изменим значение, оно автоматически обновит
-
<
односторонняя привязка: - когда мы просто хотим прочитать параметр из родительской области и не обновлять его.
-
@
это для Строковые параметры
-
&
это для Callbacks, если ваш компонент должен вывести что-то в свою родительскую область
Ответ 8
Я создал небольшой HTML файл, содержащий угловой код, демонстрирующий различия между ними:
<!DOCTYPE html>
<html>
<head>
<title>Angular</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js"></script>
</head>
<body ng-app="myApp">
<div ng-controller="myCtrl as VM">
<a my-dir
attr1="VM.sayHi('Juan')" <!-- scope: "=" -->
attr2="VM.sayHi('Juan')" <!-- scope: "@" -->
attr3="VM.sayHi('Juan')" <!-- scope: "&" -->
></a>
</div>
<script>
angular.module("myApp", [])
.controller("myCtrl", [function(){
var vm = this;
vm.sayHi = function(name){
return ("Hey there, " + name);
}
}])
.directive("myDir", [function(){
return {
scope: {
attr1: "=",
attr2: "@",
attr3: "&"
},
link: function(scope){
console.log(scope.attr1); // =, logs "Hey there, Juan"
console.log(scope.attr2); // @, logs "VM.sayHi('Juan')"
console.log(scope.attr3); // &, logs "function (a){return h(c,a)}"
console.log(scope.attr3()); // &, logs "Hey there, Juan"
}
}
}]);
</script>
</body>
</html>
Ответ 9
= - это двусторонняя привязка, которая позволяет вам иметь живые изменения внутри вашей директивы. Когда кто-то изменяет эту переменную из директивы, вы будете иметь эти измененные данные внутри своей директивы, но @ не является двухсторонней привязкой. Он работает как Текст. Вы связываете один раз, и у вас будет только его значение.
Чтобы сделать это более ясно, вы можете использовать эту замечательную статью:
Область действия AngularJS '@' и '='
Ответ 10
Я реализовал все возможные варианты в скрипте.
Он имеет все опции:
scope:{
name:'&'
},
scope:{
name:'='
},
scope:{
name:'@'
},
scope:{
},
scope:true,
https://jsfiddle.net/rishulmatta/v7xf2ujm
Ответ 11
@ свойство локальной видимости используется для доступа к строковым значениям, которые определены вне директивы.
= В тех случаях, когда вам нужно создать двустороннюю привязку между внешней областью и директивой, выделите область действия, вы можете использовать символ.
& Локальное свойство scope позволяет потребителю директивы передавать функцию, которую может вызывать директива.
Просьба проверить приведенную ниже ссылку, которая дает вам четкое понимание с примерами. Я нашел ее очень полезной, поэтому подумал об обмене ею.
http://weblogs.asp.net/dwahlin/creating-custom-angularjs-directives-part-2-isolate-scope
Ответ 12
Даже если область локальная, как и в вашем примере, вы можете получить доступ к родительской области с помощью свойства $parent
. Предположим в приведенном ниже коде, что title
определяется в родительской области. Затем вы можете получить титул как $parent.title
:
link : function(scope) { console.log(scope.$parent.title) },
template : "the parent has the title {{$parent.title}}"
Однако в большинстве случаев один и тот же эффект лучше получается с использованием атрибутов.
Пример того, где я нашел "&" нотация, которая используется "для передачи данных из изолированной области видимости через выражение и в родительскую область", полезная (и двухсторонняя привязка данных не может быть использована) была в директиве для предоставления специальной структуры данных внутри ng-repeat.
<render data = "record" deleteFunction = "dataList.splice($index,1)" ng-repeat = "record in dataList" > </render>
Одной частью рендеринга была кнопка удаления, и здесь было полезно прикрепить функцию delete из внешней области через &. Внутри рендеринговой директивы это выглядит как
scope : { data = "=", deleteFunction = "&"},
template : "... <button ng-click = "deleteFunction()"></button>"
Двухсторонняя привязка данных, т.е. data = "="
, не может использоваться, поскольку функция удаления будет выполняться в каждом цикле $digest
, что не очень хорошо, поскольку запись затем сразу же удаляется и никогда не отображается.
Ответ 13
@
и =
см. другие ответы.
Один полученный &
TL; DR;
&
получает выражение (не только как в примерах в других ответах) от родителя и устанавливает его как функцию в директиве, вызывающую выражение. И эта функция имеет возможность заменить любую переменную (даже имя функции) выражения, передав объект с переменными.
объяснил
&
является ссылкой на выражение, это означает, что если вы передаете что-то вроде
<myDirective expr="x==y"></myDirective>
в директиве это expr
будет функцией, которая вызывает выражение, например:
function expr(){return x == y}
.
поэтому в директиве html <button ng-click="expr()"></button>
вызывается выражение. В js директивы просто $scope.expr()
также вызовет выражение.
Выражение будет вызываться с помощью $scope.x и $scope.y родителя.
У вас есть возможность переопределить параметры!
Если вы установили их по вызову, например. <button ng-click="expr({x:5})"></button>
то выражение будет вызываться с вашим параметром x
и родительским параметром y
.
Вы можете переопределить оба.
Теперь вы знаете, почему работает <button ng-click="functionFromParent({x:5})"></button>
.
Поскольку он просто вызывает выражение родителя (например, <myDirective functionFromParent="function1(x)"></myDirective>
) и заменяет возможные значения вашими указанными параметрами, в этом случае x
.
это может быть:
<myDirective functionFromParent="function1(x) + 5"></myDirective>
или
<myDirective functionFromParent="function1(x) + z"></myDirective>
с детским звонком:
<button ng-click="functionFromParent({x:5, z: 4})"></button>
.
или даже с заменой функции:
<button ng-click="functionFromParent({function1: myfn, x:5, z: 4})"></button>
.
это просто выражение, неважно, является ли это функцией или многими функциями, или просто сравнением. И вы можете заменить любую переменную этого выражения.
Примеры:
шаблон директивы против вызываемого кода:
parent определил $scope.x, $scope.y:
родительский шаблон: <myDirective expr="x==y"></myDirective>
<button ng-click="expr()"></button>
вызывает $scope.x==$scope.y
<button ng-click="expr({x: 5})"></button>
звонки 5 == $scope.y
<button ng-click="expr({x:5, y:6})"></button>
вызывает 5 == 6
родитель определил $scope.function1, $scope.x, $scope.y:
родительский шаблон: <myDirective expr="function1(x) + y"></myDirective>
<button ng-click="expr()"></button>
звонки $scope.function1($scope.x) + $scope.y
<button ng-click="expr({x: 5})"></button>
звонки $scope.function1(5) + $scope.y
<button ng-click="expr({x:5, y:6})"></button>
звонки $scope.function1(5) + 6
директива имеет $scope.myFn как функцию:
<button ng-click="expr({function1: myFn, x:5, y:6})"></button>
вызывает $scope.myFn(5) + 6
Ответ 14
основное различие между ними - это просто
@ Attribute string binding
= Two-way model binding
& Callback method binding
Ответ 15
Почему мне нужно использовать "{{title}}" с "@" и "title" с помощью "="?
Когда вы используете {{title}}, для представления и оценки директивы будет передано только значение родительской области. Это ограничивается одним способом, что означает, что изменение не будет отражено в родительской области. Вы можете использовать '=', если хотите также отразить изменения, внесенные в директиву child в родительскую область. Это два пути.
Могу ли я также напрямую обращаться к родительской области, не украшая мои элемент с атрибутом?
Когда директива имеет в ней атрибут scope (scope: {}), вы больше не сможете напрямую обращаться к родительской области. Но все же можно получить доступ к нему через scope. $Parent и т.д. Если вы удалите область из директивы, к ней можно получить доступ напрямую.
В документации говорится: "Часто желательно передавать данные из изолированный объем через выражение и родительскую область", но это похоже, отлично работает с двунаправленным связыванием. Почему путь выражения лучше?
Это зависит от контекста. Если вы хотите вызывать выражение или функцию с данными, вы используете, и если вы хотите использовать общие данные, вы можете использовать метод biderectional, используя '='
Вы можете найти различия между несколькими способами передачи данных в директиву по ссылке ниже:
AngularJS - изолированные области - @vs = vs &
http://www.codeforeach.com/angularjs/angularjs-isolated-scopes-vs-vs
Ответ 16
@Связывание строки атрибута (в одну сторону)
= Двусторонняя привязка к модели
& Амп; Связывание метода обратного вызова
Ответ 17
@связывает свойство области локального/директива с оцененным значением атрибута DOM. = привязывает свойство области локальной/директивы к свойству родительской области. & binding - это передача метода в область вашей директивы, чтобы его можно было вызвать внутри вашей директивы.
@Связывание строки атрибута = привязка двухсторонней привязки и привязка метода обратного вызова