Qual é a diferença entre '@' e '=' no escopo da diretiva no AngularJS?

1067

Eu li a documentação do AngularJS sobre o tópico com cuidado e depois brinquei com uma diretiva. Aqui está o violino .

E aqui estão alguns trechos relevantes:

  • Do HTML :

    <pane bi-title="title" title="{{title}}">{{text}}</pane>
  • Na diretiva do painel:

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

Há várias coisas que não entendo:

  • Por que eu tenho que usar "{{title}}"com '@'e "title"com '='?
  • Também posso acessar o escopo pai diretamente, sem decorar meu elemento com um atributo?
  • A documentação diz "Muitas vezes é desejável passar dados do escopo isolado via expressão e para o escopo pai" , mas isso também parece funcionar bem com a ligação bidirecional. Por que a rota de expressão seria melhor?

Encontrei outro violino que também mostra a solução de expressão: http://jsfiddle.net/maxisam/QrCXh/

iwein
fonte
18
Ponto justo. A capacidade de pesquisar e encontrar respostas é importante.
7276 Jonathan
1
Em palavras simples, =é usado no escopo isolado da diretiva para ativar a ligação bidirecional e @não atualiza o modelo, apenas atualiza os valores do escopo da diretiva.
STEEL
@ iwein Por que o seu código de violino em jsfiddle.net/maxisam/QrCXh não funciona com googleapi - ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js ? Seu código só funciona se eu usar seu CDN - code.angularjs.org/1.0.1/angular-1.0.1.js
MukulSharma
Vejo muitas boas respostas abaixo, mas alguém pode apontar a documentação angular oficial que responde a essa pergunta?
John Henckel

Respostas:

1151

Por que eu tenho que usar "{{title}}" com ' @ ' e "title" com ' = '?

@ liga uma propriedade de escopo local / diretiva ao valor avaliado do atributo DOM . Se você usar title=title1ou title="title1", o valor do atributo DOM "title" é simplesmente a string title1. Se você usar title="{{title}}", o valor do atributo DOM "title" é o valor interpolado de {{title}}, portanto, a string será qualquer propriedade do escopo pai "title" que estiver configurada atualmente. Como os valores dos atributos sempre são strings, você sempre terá um valor de string para essa propriedade no escopo da diretiva ao usar @ .

= liga uma propriedade de escopo local / diretiva a uma propriedade de escopo pai . Portanto, com = , você usa o nome da propriedade modelo / escopo pai como o valor do atributo DOM. Você não pode usar {{}}s com = .

Com @, você pode fazer coisas como title="{{title}} and then some"- {{title}} é interpolada e, em seguida, a string "e alguns" é concatenada. A sequência concatenada final é o que a propriedade de escopo local / diretiva obtém. (Você não pode fazer isso com = , apenas @ .)

Com @ , você precisará usar attr.$observe('title', function(value) { ... })se precisar usar o valor em sua função de link (ing). Por exemplo, if(scope.title == "...")não funcionará como você espera. Observe que isso significa que você só pode acessar este atributo de forma assíncrona . Você não precisa usar $ observe () se estiver usando apenas o valor em um modelo. Por exemplo template: '<div>{{title}}</div>',.

Com = , você não precisa usar $ observe.

Também posso acessar o escopo pai diretamente, sem decorar meu elemento com um atributo?

Sim, mas somente se você não usar um escopo isolado. Remova esta linha da sua diretiva

scope: { ... }

e sua diretiva não criará um novo escopo. Ele usará o escopo pai. Você pode acessar todas as propriedades do escopo pai diretamente.

A documentação diz "Muitas vezes é desejável passar dados do escopo isolado por meio de uma expressão e para o escopo pai", mas isso também parece funcionar bem com a ligação bidirecional. Por que a rota de expressão seria melhor?

Sim, a ligação bidirecional permite que o escopo local / diretiva e o escopo pai compartilhem dados. "Ligação de expressão" permite que a diretiva chame uma expressão (ou função) definida por um atributo DOM - e você também pode passar dados como argumentos para a expressão ou função. Portanto, se você não precisar compartilhar dados com o pai - você apenas deseja chamar uma função definida no escopo pai - poderá usar a sintaxe & .

Veja também

Mark Rajcok
fonte
1
Huh, esse é um comportamento realmente estranho, especialmente quando não se usa interpolação e apenas tenta passar uma string. Aparentemente, a solicitação pull foi realmente mesclada nas compilações de desenvolvimento e está nas versões 1.1.5 e 1.2.0 RC. Bom neles para corrigir esse comportamento muito pouco intuitivo!
Ibrahim
50
Escrever '@' ou '=' é muito mais claro do que escrever "eval-dom" ou "parent-scope" ou qualquer outro texto legível por humanos. Boa decisão de design.
Den
13
@('at') copia o valor do 'ATtribute'. =('igual') é equivalente a dizer que a chave é igual à sua expressão. Pelo menos é assim que os mantenho em segredo.
Matt DeKrey
1
Você tem certeza de que = é apenas para propriedades de escopo pai? Qualquer expressão parece funcionar - não apenas as propriedades do escopo pai.
Jonathan Aquino
4
@ JonathanAquino, sim, isso funciona, mas @ seria mais apropriado - com foo="{{1+1}}"- porque não precisamos de ligação de dados bidirecional aqui. O ponto que tentei fazer no comentário acima é que devemos usar = somente quando a diretiva precisar de ligação de dados bidirecional. Use @ ou & caso contrário.
Mark Rajcok
542

Há um monte de grandes respostas aqui, mas eu gostaria de oferecer a minha perspectiva sobre as diferenças entre @, =e &vinculativo que provou ser útil para mim.

Todas as três ligações são maneiras de passar dados do escopo pai para o escopo isolado da diretiva por meio dos atributos do elemento:

  1. @ binding é para passar strings. Essas seqüências suportam {{}}expressões para valores interpolados. Por exemplo: . A expressão interpolada é avaliada em relação ao escopo pai da diretiva.

  2. = binding é para ligação de modelo bidirecional. O modelo no escopo pai está vinculado ao modelo no escopo isolado da diretiva. Alterações em um modelo afetam o outro e vice-versa.

  3. & binding é para passar um método para o escopo da sua diretiva, para que ele possa ser chamado dentro da sua diretiva. O método é pré-vinculado ao escopo pai da diretiva e suporta argumentos. Por exemplo, se o método for hello (name) no escopo pai, para executar o método de dentro de sua diretiva, você deve chamar $ scope.hello ({name: 'world'})

Acho que é mais fácil lembrar dessas diferenças consultando as ligações do escopo por uma descrição mais curta:

  • @ Ligação de sequência de atributos
  • = Encadernação de modelo bidirecional
  • & Ligação de método de retorno de chamada

Os símbolos também tornam mais claro o que a variável de escopo representa dentro da implementação da sua diretiva:

  • @ corda
  • = modelo
  • & método

Em ordem de utilidade (para mim de qualquer maneira):

  1. =
  2. @
  3. &
pixelbits
fonte
13
Na verdade, "&"suporta argumentos (ou melhor, locais) do formulário:, callback({foo: "some value"})que poderiam ser usados <my-dir callback="doSomething(foo)">. Caso contrário, boa resposta
New Dev
11
Deve ser aceita resposta. Aqui está um artigo conciso com a mesma informação, mas com exemplos de código adicionadas: umur.io/...
Kevin
4
& NÃO é "Ligação de método de retorno de chamada", é ligação de expressão angular. Um exemplo especial, mas não o único, é a expressão callback(argument). O que ainda não é o mesmo que callbackele.
Dmitri Zaitsev
14
Embora eu amei o quão definitiva era a resposta de classificação mais alta, achei que essa teve um impacto mais útil e, depois de ler essa, entendi muito mais a resposta anterior.
Rbnzdave
1
Concordo com o comentário acima, esta resposta é mais clara, definitiva e útil para a pergunta. Explica com detalhes suficientes que você pode usar as informações.
user3125823
64

Os =meios de ligao bidireccional, assim que uma referência a uma variável para o escopo pai. Isso significa que, quando você altera a variável na diretiva, ela também será alterada no escopo pai.

@ significa que a variável será copiada (clonada) na diretiva.

Tanto quanto eu sei, <pane bi-title="{{title}}" title="{{title}}">{{text}}</pane>deve funcionar também. bi-titlereceberá o valor da variável do escopo pai, que pode ser alterado na diretiva.

Se você precisar alterar várias variáveis ​​no escopo pai, poderá executar uma função no escopo pai de dentro da diretiva (ou transmitir dados por meio de um serviço).

asgoth
fonte
1
Sim, essa parte que recebo, veja o violino na pergunta. Mas e as partes que não são claras?
Iwein
4
o problema é que {{}} não funciona com =. = não é avaliado, mas a cadeia é usada como o nome da propriedade como está. Obrigado pela resposta!
Iwein
1
Eu não acho que = é apenas para variáveis ​​no escopo pai. Funciona com qualquer expressão (por exemplo, 1 + 1).
Jonathan Aquino
1
@JonathanAquino, você está certo ao avaliar expressões. imho isso é realmente estranho e eu não usaria dessa maneira. É esse tipo de truque inteligente que torna os escopos das diretivas tão difíceis para eu entender em primeiro lugar.
Iwein
1
Eu sou o único que acha que esta resposta está errada! '=' angular médio espera uma expressão javascript e fará um mapeamento bidirecional se uma variável de escopo for passada. Enquanto @ mean angular espera uma String e tudo isso. De fato, é verdade que se você usar @ em combinação com {{}}, clonará o valor da variável. Mas não é a definição de @!
Luc DUZAN
39

Se você gostaria de ver mais como isso funciona com um exemplo ao vivo. 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>"
    };
});
Juan Mendez
fonte
2
Existem vários exemplos vinculados na pergunta e na resposta principal. O que isso adiciona?
iwein 24/11
10
@ iwein, acrescenta clareza. Se eu pudesse entender e assimilar exemplos completos, não precisaria deste site.
Tony Ennis
3
Juan, talvez conserte seus erros de digitação? 'transclude' está incorreto. melhor ainda, remova-o (e tudo o mais, como 'substituir') que não contribui diretamente para o problema, para que sua solução seja ainda mais simples e clara. +1 para o exemplo.
Tony Ennis
obrigado @AnikISlamAbhi pela edição. Gostaria de contribuir mais e fico feliz que alguns achem minhas amostras úteis. Esse é o objetivo principal.
Juan Mendez
Exemplo incompleto. Na sua demonstração, você está alterando apenas o valor bidirecional. Você nem está tentando alterar um valor que tenha escopo isolado. Portanto, não demonstrou adequadamente como o escopo funciona nas diretivas.
Sudarshan_SMD
38

@ obter como string

  • Isso não cria nenhuma ligação. Você está simplesmente recebendo a palavra que você passou como uma string

= Ligação de 2 vias

  • as alterações feitas no controlador serão refletidas na referência mantida pela diretiva e vice-versa

& Isso se comporta um pouco diferente, porque o escopo recebe uma função que retorna o objeto que foi passado . Estou assumindo que isso era necessário para fazê-lo funcionar. O violino deve deixar isso claro.

  • Depois de chamar essa função getter, o objeto resultante se comporta da seguinte maneira:
    • se uma função foi aprovada: a função é executada no fechamento do pai (controlador) quando chamada
    • se uma não função foi passada: simplesmente obtenha uma cópia local do objeto que não possui ligações


Esse violino deve demonstrar como eles funcionam . Preste atenção especial às funções do escopo com get...o nome para entender melhor o que quero dizer sobre&

geg
fonte
36

Existem três maneiras pelas quais o escopo pode ser adicionado na diretiva:

  1. Escopo pai : esta é a herança do escopo padrão.

A diretiva e seu escopo pai (controlador / diretiva dentro do qual ela se encontra) são os mesmos. Portanto, quaisquer alterações feitas nas variáveis ​​de escopo dentro da diretiva também são refletidas no controlador pai. Você não precisa especificar isso, pois é o padrão.

  1. Escopo filho : a diretiva cria um escopo filho que herda do escopo pai, se você especificar a variável de escopo da diretiva como verdadeira.

Aqui, se você alterar as variáveis ​​de escopo dentro da diretiva, ela não será refletida no escopo pai, mas se você alterar a propriedade de uma variável de escopo, isso será refletido no escopo pai, conforme você realmente modificou a variável de escopo do pai. .

Exemplo,

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. Escopo isolado : É usado quando você deseja criar o escopo que não herda do escopo do controlador.

Isso acontece quando você cria plugins, pois isso torna a diretiva genérica, pois pode ser colocada em qualquer HTML e não é afetada pelo escopo pai.

Agora, se você não deseja nenhuma interação com o escopo pai, basta especificar o escopo como um objeto vazio. gostar,

scope: {} //this does not interact with the parent scope in any way

Principalmente esse não é o caso, pois precisamos de alguma interação com o escopo pai, portanto, queremos que alguns dos valores / alterações sejam transmitidos. Por esse motivo, usamos:

1. "@"   (  Text binding / one-way binding )
2. "="   ( Direct model binding / two-way binding )
3. "&"   ( Behaviour binding / Method binding  )

@ significa que as alterações no escopo do controlador serão refletidas no escopo da diretiva, mas se você modificar o valor no escopo da diretiva, a variável do escopo do controlador não será afetada.

@ sempre espera que o atributo mapeado seja uma expressão. Isto é muito importante; porque para fazer o prefixo "@" funcionar, precisamos agrupar o valor do atributo dentro de {{}}.

= é bidirecional, portanto, se você alterar a variável no escopo da diretiva, a variável do escopo do controlador também será afetada

& é usado para vincular o método do escopo do controlador para que, se necessário, possamos chamá-lo da diretiva

A vantagem aqui é que o nome da variável não precisa ser o mesmo no escopo do controlador e no escopo da diretiva.

Por exemplo, o escopo da diretiva possui uma variável "dirVar" que é sincronizada com a variável "contVar" do escopo do controlador. Isso dá muita força e generalização à diretiva, pois um controlador pode sincronizar com a variável v1, enquanto outro controlador que usa a mesma diretiva pode solicitar ao dirVar que sincronize com a variável v2.

Abaixo está o exemplo de uso:

A diretiva e o controlador são:

 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
        }
    };
});

E o html (observe a diferença entre @ e =):

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

Aqui está um link para o blog que descreve bem.

Kop4lyf
fonte
& não é "Ligação de comportamento" nem "Ligação de método", é ligação de expressão angular.
Dmitri Zaitsev
20

Simplesmente podemos usar: -

  1. @ : - para valores de String para ligação de dados unidirecionais. de uma maneira, ligação de dados, você só pode passar o valor do escopo para a diretiva

  2. = : - para o valor do objeto para ligação de dados bidirecional. na ligação de dados bidirecional, você pode alterar o valor do escopo na diretiva e também no html.

  3. & : - para métodos e funções.

EDITAR

Em nossa definição de Componente para Angular versão 1.5 E acima,
existem quatro tipos diferentes de ligações:

  1. = Associação de dados bidirecional : - se alterarmos o valor, ele será atualizado automaticamente
  2. < ligação unidirecional : - quando queremos apenas ler um parâmetro de um escopo pai e não atualizá-lo.

  3. @isto é para parâmetros de string

  4. &isso é para retornos de chamada , caso seu componente precise gerar algo para seu escopo pai

ojus kulkarni
fonte
13

Eu criei um pequeno arquivo HTML que contém código Angular, demonstrando as diferenças entre eles:

<!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>
RobertAKARobin
fonte
6

O caminho = é uma ligação bidirecional , que permite que você tenha alterações em tempo real dentro de sua diretiva. Quando alguém alterar essa variável fora da diretiva, você terá esses dados alterados dentro da diretiva, mas @ way não é uma ligação bidirecional . Funciona como texto . Você liga uma vez e terá apenas seu valor.

Para ficar mais claro, você pode usar este excelente artigo:

Âmbito da diretiva AngularJS '@' e '='

Hazarapet Tunanyan
fonte
6

Essa pergunta já foi derrotada até a morte, mas vou compartilhar isso de qualquer maneira, caso outra pessoa lá fora esteja lutando com a bagunça horrível que é o escopo do AngularJS. Esta cobertura vontade =, <, @, &e ::. A gravação completa pode ser encontrada aqui .


=estabelece uma ligação bidirecional. Alterar a propriedade no pai resultará em uma mudança no filho e vice-versa.


<estabelece uma ligação unidirecional, pai para filho. Alterar a propriedade no pai resultará em um filho, mas alterar a propriedade do filho não afetará a propriedade do pai.


@atribuirá à propriedade filho o valor da string do atributo tag. Se o atributo contiver uma expressão , a propriedade filho será atualizada sempre que a expressão for avaliada para uma sequência diferente. Por exemplo:

<child-component description="The movie title is {{$ctrl.movie.title}}" />
bindings: {
    description: '@', 
}

Aqui, a descriptionpropriedade no escopo filho será o valor atual da expressão "The movie title is {{$ctrl.movie.title}}", onde movieé um objeto no escopo pai.


&é um pouco complicado e, de fato, parece não haver uma razão convincente para usá-lo. Permite avaliar uma expressão no escopo pai, substituindo parâmetros por variáveis ​​do escopo filho. Um exemplo ( plunk ):

<child-component 
  foo = "myVar + $ctrl.parentVar + myOtherVar"
</child-component>
angular.module('heroApp').component('childComponent', {
  template: "<div>{{  $ctrl.parentFoo({myVar:5, myOtherVar:'xyz'})  }}</div>",
  bindings: {
    parentFoo: '&foo'
  }
});

Dada parentVar=10, a expressão parentFoo({myVar:5, myOtherVar:'xyz'})será avaliada 5 + 10 + 'xyz'e o componente será renderizado como:

<div>15xyz</div>

Quando você gostaria de usar essa funcionalidade complicada? &é frequentemente usado por pessoas para transmitir ao escopo filho uma função de retorno de chamada no escopo pai. Na realidade, no entanto, o mesmo efeito pode ser alcançado usando '<' para passar a função, que é mais direta e evita a sintaxe estranha das chaves para passar parâmetros ({myVar:5, myOtherVar:'xyz'} ). Considerar:

Retorno de chamada usando &:

<child-component parent-foo="$ctrl.foo(bar)"/>
angular.module('heroApp').component('childComponent', {
  template: '<button ng-click="$ctrl.parentFoo({bar:'xyz'})">Call foo in parent</button>',
  bindings: {
    parentFoo: '&'
  }
});

Retorno de chamada usando <:

<child-component parent-foo="$ctrl.foo"/>
angular.module('heroApp').component('childComponent', {
  template: '<button ng-click="$ctrl.parentFoo('xyz')">Call foo in parent</button>',
  bindings: {
    parentFoo: '<'
  }
});

Observe que objetos (e matrizes) são passados ​​por referência ao escopo filho, não copiados. O que isso significa é que, mesmo que seja uma ligação unidirecional, você está trabalhando com o mesmo objeto no escopo pai e no filho.


Para ver os diferentes prefixos em ação, abra este plunk .

Ligação única (inicialização) usando ::

[Documentos oficiais]
As versões posteriores do AngularJS apresentam a opção de ter uma associação única, em que a propriedade do escopo filho é atualizada apenas uma vez. Isso melhora o desempenho, eliminando a necessidade de observar a propriedade pai. A sintaxe é diferente da acima; para declarar uma ligação única, você adiciona ::na frente da expressão na tag component :

<child-component 
  tagline = "::$ctrl.tagline">
</child-component>

Isso propagará o valor taglinepara o escopo filho sem estabelecer uma ligação unidirecional ou bidirecional. Nota : se taglineestiver inicialmente undefinedno escopo pai, o angular o observará até que ele mude e faça uma atualização única da propriedade correspondente no escopo filho.

Sumário

A tabela abaixo mostra como os prefixos funcionam, dependendo se a propriedade é um objeto, matriz, string, etc.

Como as várias ligações do escopo isolado funcionam

Mihail Kostira
fonte
4

A propriedade @ local scope é usada para acessar valores de string definidos fora da diretiva.

= Nos casos em que é necessário criar uma ligação bidirecional entre o escopo externo e o escopo isolado da diretiva, você pode usar o caractere =.

A propriedade & local scope permite ao consumidor de uma diretiva passar uma função que a diretiva pode chamar.

Por favor, verifique o link abaixo, que fornece uma compreensão clara com os exemplos. Achei realmente muito útil, por isso pensei em compartilhá-lo.

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

Rafael
fonte
3

Mesmo quando o escopo é local, como no seu exemplo, você pode acessar o escopo pai pela propriedade $parent. Suponha no código abaixo, titledefinido no escopo pai. Você pode acessar o título como $parent.title:

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

No entanto, na maioria dos casos, o mesmo efeito é melhor obtido usando atributos.

Um exemplo de onde encontrei a notação "&", que é usada "para passar dados do escopo isolado por meio de uma expressão e para o escopo pai", útil (e uma ligação de dados bidirecional não poderia ser usada) estava em uma diretiva para renderizar uma estrutura de dados especial dentro de uma repetição de ng.

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

Uma parte da renderização era um botão de exclusão e aqui era útil anexar uma função de exclusão do escopo externo via &. Dentro da diretiva de renderização, parece

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

A ligação de dados bidirecional, ou seja, data = "="não pode ser usada, pois a função de exclusão seria executada em todos os $digestciclos, o que não é bom, pois o registro é excluído imediatamente e nunca é renderizado.

user3750988
fonte
3

Eu implementei todas as opções possíveis em um violino.

Ele lida com todas as opções:

scope:{
    name:'&'
},

scope:{
    name:'='
},

scope:{
    name:'@'
},

scope:{

},

scope:true,

https://jsfiddle.net/rishulmatta/v7xf2ujm

Rishul Matta
fonte
3

a principal diferença entre eles é apenas

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

@ e = veja outras respostas.

Uma dica sobre TL; DR; obtém expressão (não apenas funciona como nos exemplos de outras respostas) de um pai e a define como uma função na diretiva, que chama a expressão E essa função tem a capacidade de substituir qualquer variável&

& (nome da função par) de expressão, passando um objeto pelas variáveis.

explicou
& é uma referência de expressão, isso significa que se você passar algo como <myDirective expr="x==y"></myDirective>
na directiva esta exprserá uma função, que chama a expressão, como:
function expr(){return x == y}.
assim, no html da diretiva <button ng-click="expr()"></button>chamará a expressão Nos js da diretiva, apenas $scope.expr()chamamos a expressão também.
A expressão será chamada com $ scope.xe $ scope.y do pai.
Você tem a capacidade de substituir os parâmetros!
Se você os definir por chamada, por exemplo <button ng-click="expr({x:5})"></button>
, a expressão será chamada com o seu parâmetro xe o parâmetro dos pais y.
Você pode substituir ambos.
Agora você sabe, por que <button ng-click="functionFromParent({x:5})"></button>funciona.
Porque apenas chama a expressão de pai (por exemplo,<myDirective functionFromParent="function1(x)"></myDirective>) e substitui os valores possíveis pelos parâmetros especificados, neste caso x.
poderia ser:
<myDirective functionFromParent="function1(x) + 5"></myDirective>
ou
<myDirective functionFromParent="function1(x) + z"></myDirective>
com apelo infantil:
<button ng-click="functionFromParent({x:5, z: 4})"></button>.
ou mesmo com a substituição de função:
<button ng-click="functionFromParent({function1: myfn, x:5, z: 4})"></button>.

é apenas uma expressão, não importa se é uma função, ou muitas funções, ou apenas comparação. E você pode substituir qualquer variável dessa expressão.

Exemplos:
modelo de diretiva vs código chamado:
pai definiu $ scope.x, $ scope.y:
modelo pai: <myDirective expr="x==y"></myDirective>
<button ng-click="expr()"></button>calls $scope.x==$scope.y
<button ng-click="expr({x: 5})"></button>calls 5 == $scope.y
<button ng-click="expr({x:5, y:6})"></button>calls5 == 6

pai definiu $ scope.function1, $ scope.x, $ scope.y:
modelo pai:<myDirective expr="function1(x) + y"></myDirective>

<button ng-click="expr()"></button>calls $scope.function1($scope.x) + $scope.y
<button ng-click="expr({x: 5})"></button>calls $scope.function1(5) + $scope.y
<button ng-click="expr({x:5, y:6})"></button>calls $scope.function1(5) + 6
diretiva possui $ scope.myFn como função:
<button ng-click="expr({function1: myFn, x:5, y:6})"></button> calls$scope.myFn(5) + 6

ya_dimon
fonte
0

Por que eu tenho que usar "{{title}}" com '@' e "title" com '='?

Quando você usa o {{title}}, apenas o valor do escopo pai será passado para a exibição da diretiva e avaliado. Isso é limitado de uma maneira, o que significa que as alterações não serão refletidas no escopo pai. Você pode usar '=' quando quiser refletir as alterações feitas na diretiva filho no escopo pai também. Este é o caminho.

Também posso acessar o escopo pai diretamente, sem decorar meu elemento com um atributo?

Quando a diretiva possui o atributo scope (scope: {}), você não poderá mais acessar o escopo pai diretamente. Mas ainda é possível acessá-lo através do escopo. $ Parent etc. Se você remover o escopo da diretiva, ele poderá ser acessado diretamente.

A documentação diz "Muitas vezes é desejável passar dados do escopo isolado por meio de uma expressão e para o escopo pai", mas isso também parece funcionar bem com a ligação bidirecional. Por que a rota de expressão seria melhor?

Depende do contexto. Se você deseja chamar uma expressão ou função com dados, você usa & e se deseja compartilhar dados, pode usar a maneira bidirecional usando '='

Você pode encontrar as diferenças entre várias maneiras de passar dados para a diretiva no link abaixo:

AngularJS - Escopos isolados - @ vs = vs &

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

Prashanth
fonte
0

@ Vinculação de string de atributo (unidirecional) = Vinculação de modelo bidirecional e vinculação de método de retorno de chamada

Jatin Patel
fonte
0

@ liga uma propriedade de escopo local / diretiva ao valor avaliado do atributo DOM. = liga uma propriedade de escopo local / diretiva a uma propriedade de escopo pai. & binding é para passar um método para o escopo da sua diretiva, para que ele possa ser chamado dentro da sua diretiva.

@ Vinculação de string de atributo = Vinculação de modelo bidirecional e vinculação de método de retorno de chamada

Ashish Kamble
fonte