it-swarm.com.ru

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

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

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

  • Из HTML:

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

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

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

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

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

1041
iwein

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

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

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

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

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

С = вам не нужно использовать $ наблюдаем.

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

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

scope: { ... }

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

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

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

Смотрите также

1134
Mark Rajcok

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

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

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

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

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

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

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

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

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

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

  1. знак равно
  2. @
  3. &
532
pixelbits

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

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

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

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

63
asgoth

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

@ получить в виде строки

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

= 2-х стороннее связывание

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

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

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


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

37
geg

Существует три способа добавления области действия в директиву:

  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>

Вот ссылка к блогу, который описывает это красиво.

33
Kop4lyf

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

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

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

  3. &: - для методов и функций.

Правка

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

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

  3. @ это для строковые параметры

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

20
ojus kulkarni

Я создал небольшой HTML-файл, содержащий код Angular, демонстрирующий различия между ними:

<!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>
11
RobertAKARobin

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

Чтобы сделать это более понятным, вы можете использовать эту замечательную статью:

Область Директив AngularJS '@' и '='

6
Hazarapet Tunanyan

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

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

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

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

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

3
Raphael

Даже если область является локальной, как в вашем примере, вы можете получить доступ к родительской области через свойство $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>

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

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

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

3
user3750988

Я реализовал все возможные варианты в скрипке.

Здесь рассматриваются все варианты:

scope:{
    name:'&'
},

scope:{
    name:'='
},

scope:{
    name:'@'
},

scope:{

},

scope:true,

https://jsfiddle.net/rishulmatta/v7xf2ujm

3
Rishul Matta

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

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

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

Один получил о &
TL; DR;
& получает выражение (не только функцию, как в примерах в других ответах) от родителя, и устанавливает его как функцию в директиве, которая вызывает выражение. И эта функция имеет возможность заменить любую переменную (даже имя функции) выражения, передавая объект с переменными.

объяснено
& является ссылкой на выражение, это означает, что если вы передадите что-то вроде <myDirective expr="x==y"></myDirective>
в директиве this 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> работает.
Поскольку он просто вызывает выражение 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>.

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

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

1
ya_dimon

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

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

0
Ashish Kamble

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

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

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

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

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

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

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

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

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

0
Prashanth

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

0
Jatin Patel