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/
=
é 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.Respostas:
@ liga uma propriedade de escopo local / diretiva ao valor avaliado do atributo DOM . Se você usar
title=title1
outitle="title1"
, o valor do atributo DOM "title" é simplesmente a stringtitle1
. Se você usartitle="{{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 exemplotemplate: '<div>{{title}}</div>'
,.Com = , você não precisa usar $ observe.
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.
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
fonte
@
('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.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.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:
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 chamadaOs 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étodoEm ordem de utilidade (para mim de qualquer maneira):
fonte
"&"
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 respostacallback(argument)
. O que ainda não é o mesmo quecallback
ele.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-title
receberá 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).
fonte
Se você gostaria de ver mais como isso funciona com um exemplo ao vivo. http://jsfiddle.net/juanmendez/k6chmnch/
fonte
@
obter como string=
Ligação de 2 vias&
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.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&
fonte
Existem três maneiras pelas quais o escopo pode ser adicionado na diretiva:
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.
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,
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,
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:
@ 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:
E o html (observe a diferença entre @ e =):
Aqui está um link para o blog que descreve bem.
fonte
Simplesmente podemos usar: -
@ : - 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
= : - 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.
& : - 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:
=
Associação de dados bidirecional : - se alterarmos o valor, ele será atualizado automaticamente<
ligação unidirecional : - quando queremos apenas ler um parâmetro de um escopo pai e não atualizá-lo.@
isto é para parâmetros de string&
isso é para retornos de chamada , caso seu componente precise gerar algo para seu escopo paifonte
Eu criei um pequeno arquivo HTML que contém código Angular, demonstrando as diferenças entre eles:
fonte
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 '='
fonte
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:Aqui, a
description
propriedade no escopo filho será o valor atual da expressão"The movie title is {{$ctrl.movie.title}}"
, ondemovie
é 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 ):Dada
parentVar=10
, a expressãoparentFoo({myVar:5, myOtherVar:'xyz'})
será avaliada5 + 10 + 'xyz'
e o componente será renderizado como: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
&
:Retorno de chamada usando
<
: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 :Isso propagará o valor
tagline
para o escopo filho sem estabelecer uma ligação unidirecional ou bidirecional. Nota : setagline
estiver inicialmenteundefined
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.
fonte
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
fonte
Mesmo quando o escopo é local, como no seu exemplo, você pode acessar o escopo pai pela propriedade
$parent
. Suponha no código abaixo,title
definido no escopo pai. Você pode acessar o título como$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.
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
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$digest
ciclos, o que não é bom, pois o registro é excluído imediatamente e nunca é renderizado.fonte
Eu implementei todas as opções possíveis em um violino.
Ele lida com todas as opções:
https://jsfiddle.net/rishulmatta/v7xf2ujm
fonte
a principal diferença entre eles é apenas
fonte
@
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
expr
será 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
x
e o parâmetro dos paisy
.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 casox
.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>
calls5 == $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
fonte
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.
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.
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
fonte
@ Vinculação de string de atributo (unidirecional) = Vinculação de modelo bidirecional e vinculação de método de retorno de chamada
fonte
@ 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
fonte