В чем разница между " @ " и " = " в области директивы в AngularJS?

Я внимательно прочитал документацию AngularJS по этой теме, а затем повозился с директивой. Вот скрипка.

и вот некоторые соответствующие фрагменты:

  • из HTML:

    <pane bi-title="title" title="{{title}}">{{text}}</pane>
    
  • из директивы панели:

    scope: { biTitle: '=', title: '@', bar: '=' },
    

есть несколько вещей, которые я не понимаю:

  • почему я должен использовать "{{title}}" С '@' и "title" с '='?
  • могу ли я также получить доступ к родительской области напрямую, не украшая свой элемент атрибутом?
  • в документации написано "часто желательно передавать данные из изолированной области через выражение и в родительскую область", но это, похоже, отлично работает и с двунаправленной привязкой. Почему маршрут выражения должен быть лучше?

Я нашел еще одну скрипку, которая также показывает решение выражения: http://jsfiddle.net/maxisam/QrCXh/

17 ответов


почему я должен использовать "{{title}} " С '@ и "название" с '='?

@ связывает свойство Local / directive scope с оцененное значение атрибута DOM. Если вы используете title=title1 или title="title1", значение атрибута DOM "title" - это просто строка title1. Если вы используете title="{{title}}", значение атрибута DOM "title" является интерполированным значением {{title}}, следовательно, строка будет независимо от того, какое свойство родительской области "title" В настоящее время установлено. Поскольку значения атрибутов всегда являются строками, при использовании @.

= связывает свойство Local / directive scope с свойство родительской области. Так и с =, вы используете родительскую модель / имя свойства области в качестве значения атрибута DOM. Вы не можете использовать {{}}s с =.

С @, вы можете делать вещи, как title="{{title}} and then some" -- {{title}} интерполируется, затем с ним связывается строка "и их некоторые". Конечная объединенная строка-это то, что получает свойство Local / directive scope. (Вы не можете сделать это с помощью =, только @.)

С @, вам нужно будет использовать attr.$observe('title', function(value) { ... }) если вам нужно использовать значение в функции link(ing). Е. Г., if(scope.title == "...") не будет работать, как вы ожидаете. Обратите внимание, что это означает, что вы можете получить доступ только к этому атрибуту асинхронно. Вам не нужно использовать $observe (), если вы используете только значение в шаблоне. Е. Г., template: '<div>{{title}}</div>'.

С =, вам не нужно использовать $observe.

могу ли я также получить доступ к родительской области напрямую, не украшая свой элемент атрибутом?

да, но только если вы не используете изолированный объем. Удалить это строка из вашей директивы

scope: { ... }

и тогда ваша директива не создает новую область. Он будет использовать родительскую область. Затем можно получить доступ ко всем свойствам родительской области напрямую.

в документации говорится: "часто желательно передавать данные из изолированной области через выражение и в родительскую область", но это, похоже, отлично работает и с двунаправленной привязкой. Почему маршрут выражения должен быть лучше?

да, двунаправленная привязка позволяет локальной / директивной области и родительской области обмениваться данными. "Привязка выражения" позволяет директиве вызывать выражение (или функцию), определенное атрибутом DOM, а также передавать данные в качестве аргументов выражению или функции. Итак, если вам не нужно делиться данными с родителем - вы просто хотите вызвать функцию, определенную в родительской области, - вы можете использовать & синтаксис.

см. также


есть много хороших ответов здесь, но я хотел бы предложить свою точку зрения на различия между @, = и & привязка, которая оказалась полезной для меня.

все три привязки-это способы передачи данных из родительской области в изолированную область вашей директивы через атрибуты элемента:

  1. @ привязка для передачи строк. Эти строки поддерживают {{}} выражения для интерполированное значение. Например: . Интерполированное выражение вычисляется по родительской директивы.

  2. = привязка для двухсторонней привязки модели. Модель в родительской области связан с моделью в изолированной области действия директивы. Изменения одна модель влияет на другую, и наоборот.

  3. & привязка для передачи метода в область вашего директивы так что его можно вызвать в рамках вашей директивы. Метод предварительно привязан к родительской директивы, и поддерживает аргументы. Например, если метод hello (name) в родительской области, то в чтобы выполнить метод изнутри вашей директивы, вы должны вызовите $scope.привет ({name: 'world'})

Я считаю, что легче запомнить эти различия, ссылаясь на переплетах области, короче описание:

  • @ привязка строки атрибута
  • = двусторонняя привязка модели
  • & привязка метода обратного вызова

символы также проясняют, что переменная scope представляет внутри реализации вашей директивы:

  • @ строка
  • = модель
  • & метод

в порядке полезности (для меня во всяком случае):

  1. =
  2. @
  3. &

на = означает двунаправленную привязку, поэтому ссылка на переменную в родительской области. Это означает,что при изменении переменной в директиве она также будет изменена в родительской области.

@ означает, что переменная будет скопирована (клонирована) в директиву.

насколько я знаю, <pane bi-title="{{title}}" title="{{title}}">{{text}}</pane> тоже должен работать. bi-title получит значение переменной родительской области, которое может быть изменено в директиве.

Если вам нужно изменить несколько переменных в родительской области, вы можете выполнить функцию в родительской области из директивы (или передать данные через службу).


Если вы хотите увидеть больше, как это работать с живым примером. 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>"
    };
});

@ сделать как строку

  • это не создает никаких привязок вообще. Вы просто получаете слово, которое вы передали в виде строки

= 2 способ привязки

  • изменения, внесенные с контроллера, будут отражены в ссылке, содержащейся в директиве, и наоборот

& это ведет себя немного иначе, потому что область получает функцию, которая возвращает объект, который был принят в. Я предполагаю, что это было необходимо, чтобы заставить его работать. скрипка должна прояснить это.

  • после вызова этой функции геттера результирующий объект ведет себя следующим образом:
    • если функции было передано: затем функция выполняется в Родительском (контроллерном) закрытии при вызове
    • если функции был передан в: просто получить локальная копия объекта, не имеющего Привязок


эта скрипка должна продемонстрировать, как они работают. Обратите особое внимание на функции scope с помощью get... В имя, в надежде лучше понять, что я имею в виду о &


в директиве можно добавить три способа:

  1. родительской области: это наследование области по умолчанию.

директива и ее родительская область(контроллер/директива, внутри которой она находится) одинаковы. Таким образом, любые изменения, внесенные в переменные области внутри директивы, также отражаются в Родительском контроллере. Вам не нужно указывать это, поскольку это значение по умолчанию.

  1. сферы ребенка: директива создает дочернюю область, которая наследуется от родительской области, если переменная области директивы указана как 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.
        }
    };
});
  1. изолированные области: Это используется, когда вы хотите создать область, которая не наследуется от области контроллера.

это происходит, когда вы создаете плагины, так как это делает директиву универсальной, так как она может быть помещена в любой 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 (обратите внимание на разницу для @ и =):

<div my-directive
  class="directive"
  name="{{name}}"
  reverse="reverseName()"
  color="color" >
</div>

здесь ссылке в блог, который описывает его хорошо.


просто мы можем использовать:-

  1. @ : - для строковых значений для односторонней привязки данных. одним из способов привязки данных вы можете передать значение области только директиве

  2. = : - для значения объекта для двусторонней привязки данных. в двухсторонней привязке данных вы можете изменить значение области в директиве, а также в html.

  3. & :- методы и функции.

редактировать

в нашем компонент определение Угловое версия 1.5 и выше
существует четыре разных типа Привязок:

  1. = двусторонняя привязка данных : - если мы изменим значение, оно автоматически обновит
  2. < один из способов привязки : - когда мы просто хотим прочитать параметр из родительской области и не обновлять он.

  3. @ это Параметры Строки

  4. & это обратные вызовы в случае, если ваш компонент должен вывести что-то в свою родительскую область


Я создал небольшой 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>

на = путь 2-способ привязки, что позволяет вам иметь live изменения внутри вашей директивы. Когда кто-то изменяет эту переменную из директивы, у вас будут эти измененные данные внутри вашей директивы, но @ кстати не двусторонняя привязка. Он работает как текст. Вы связываете один раз, и у вас будет только его ценность.

чтобы получить его более четко, вы можете использовать это здорово статья:

область действия директивы AngularJS ' @ 'и'='


@ local scope используется для доступа к строковым значениям, определенным вне директивы.

= в случаях, когда вам нужно создать двустороннюю привязку между внешней областью и областью изоляции директивы, вы можете использовать символ=.

& local scope позволяет потребителю директивы передать функцию, которую может вызвать директива.

пожалуйста, проверьте ссылку ниже, которая дает вы ясно понимаете с примерами.Я нашел это очень полезным, поэтому подумал о том, чтобы поделиться им.

http://weblogs.asp.net/dwahlin/creating-custom-angularjs-directives-part-2-isolate-scope


я реализовал все возможные варианты в огурчик.

Он имеет дело со всеми вариантами:

scope:{
    name:'&'
},

scope:{
    name:'='
},

scope:{
    name:'@'
},

scope:{

},

scope:true,

https://jsfiddle.net/rishulmatta/v7xf2ujm


даже при этом местные, как в вашем примере, вы можете получить доступ к родительской области через свойство $parent. Предположим в коде ниже, что title определяется в родительской области. Затем вы можете получить доступ к заголовку как $parent.title:

link : function(scope) { console.log(scope.$parent.title) },
template : "the parent has the title {{$parent.title}}"

однако в большинстве случаев тот же эффект лучше получается с использованием атрибутов.

пример того, где я нашел нотацию"&", которая используется "для передачи данных из изолированной области через выражение и в родительскую область", полезно (и двусторонняя привязка данных не может быть использована) была в директиве для рендеринга специальной структуры данных внутри ng-повтора.

<render data = "record" deleteFunction = "dataList.splice($index,1)" ng-repeat = "record in dataList" > </render>

одна часть рендеринга была кнопкой удаления, и здесь было полезно прикрепить функцию deletefunction из внешней области через &. Внутри директивы render это выглядит как

scope : { data = "=", deleteFunction = "&"},
template : "... <button ng-click = "deleteFunction()"></button>"

2-способ привязки данных, т. е. data = "=" не может использоваться как функция удаления будет работать на каждом $digest цикл, который не хорош, так как запись затем сразу удаляется и никогда не отображается.


@ и = посмотреть другие ответы.

один понял о &
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.у родителя.
Вы есть возможность переопределить параметры!
Если вы установите их по вызову, например <button ng-click="expr({x:5})"></button>
тогда выражение будет вызываться с параметром и родители y.
Вы можете переопределить оба.
Теперь вы знаете, почему <button ng-click="functionFromParent({x:5})"></button> строительство.
Потому что он просто вызывает выражение parent (например,<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>.

это просто выражение, не имеет значения, является ли оно функцией, или многими функциями, или просто сравнением. И вы можете заменить любой переменная этого выражения.

примеры:
шаблон директивы против вызываемого кода:
родитель определил $масштаб.х, $объем.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.х, $объем.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


основное различие между ними-это просто

@ Attribute string binding
= Two-way model binding
& Callback method binding

почему я должен использовать "{{title}} " С " @ " и "title " С"="?

при использовании {{title}} В представление директивы и вычисляется только значение родительской области. Это ограничено одним способом, что означает, что изменение не будет отражено в родительской области. Вы можете использовать'=', если хотите отразить изменения, внесенные в дочернюю директиву в родительскую область. Это два пути.

могу ли я также получить доступ к родительской области напрямую, без украшать мой элемент с атрибутом?

когда директива имеет атрибут scope (scope: {}), вы больше не сможете напрямую обращаться к родительской области. Но все же к нему можно получить доступ через scope.$родителя и т. д. Если удалить область из директивы, к ней можно получить прямой доступ.

в документации говорится: "часто желательно передавать данные из изолированная область через выражение и к родительской области", но это кажется, работает отлично с двунаправленной привязкой тоже. Зачем выражение маршрута будет лучше?

Это зависит от контекста. Если вы хотите вызвать выражение или функцию с данными, вы используете & , и если вы хотите поделиться данными , вы можете использовать biderectional способ, используя '='

вы можете найти различия между несколькими способами передачи данных директиве по ссылке ниже:

AngularJS-изолированные области - @ vs = vs &

http://www.codeforeach.com/angularjs/angularjs-isolated-scopes-vs-vs


@ привязка строки атрибута (в одну сторону) = Двусторонняя привязка модели & Привязка метода обратного вызова


@ связывает свойство Local / directive scope с вычисляемым значением атрибута DOM. = связывает свойство локальной / директивной области со свойством родительской области. & binding предназначен для передачи метода в область действия директивы, чтобы его можно было вызвать в пределах директивы.

@ привязка строки атрибута = Двусторонняя привязка модели & Привязка метода обратного вызова