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 description
propriedade 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 tagline
para o escopo filho sem estabelecer uma ligação unidirecional ou bidirecional. Nota : se tagline
estiver inicialmente undefined
no 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.