Pesquisa de site

javascript - Qual é a diferença entre & vs @ e=no angularJS


Sou muito novo no AngularJS. Alguém pode me explicar a diferença entre esses operadores do AngularJS: &, @ e = ao isolar o escopo com um exemplo apropriado.

Resposta #1

@ permite que um valor definido no atributo da diretiva seja passado para o escopo isolado da diretiva. O valor pode ser uma string simples (myattr="hello") ou pode ser uma string interpolada do AngularJS com expressões embutidas (myattr="my_{{helloText}}"). Pense nisso como uma comunicação “unidirecional” do escopo pai para a diretiva filha. John Lindquist tem uma série de screencasts curtos explicando cada um desses casos. Screencast sobre @ está aqui: https://egghead.io/lessons/angularjs-isolate-scope-attribute-binding

& permite que o escopo isolado da diretiva passe valores para o escopo pai para avaliação na expressão definida no atributo. Observe que o atributo da diretiva é implicitamente uma expressão e não utiliza a sintaxe de expressão com chaves duplas. Esta é um pouco mais difícil de explicar em texto. Screencast sobre & está aqui: https://egghead.io/lessons/angularjs-isolate-scope-expression-binding

= configura uma expressão de ligação bidirecional entre o escopo isolado da diretiva e o escopo pai. Alterações no escopo filho são propagadas para o pai e vice-versa. Pense em=como uma combinação de @ e &. Screencast sobre=está aqui: https://egghead.io/lessons/angularjs-isolate-scope-two-way-binding

E finalmente, aqui está um screencast que mostra os três usados juntos em uma única visualização: https://egghead.io/lessons/angularjs-isolate-scope-review

Resposta #2

Gostaria de explicar os conceitos sob a perspectiva da herança por protótipo do JavaScript. Espero ajudar a entender.

Existem três opções para definir o escopo de uma diretiva:

  1. scope: false: padrão do Angular. O escopo da diretiva é exatamente o mesmo do seu escopo pai (parentScope).
  2. scope: true: O Angular cria um escopo para esta diretiva. O escopo herda prototipicamente de parentScope.
  3. scope: {...}: escopo isolado é explicado abaixo.

Especificar scope: {...} define um isolatedScope. Um isolatedScope não herda propriedades do parentScope, embora isolatedScope.$parent === parentScope. Ele é definido através de:

app.directive("myDirective", function() {
    return {
        scope: {
            ... // defining scope means that 'no inheritance from parent'.
        },
    }
})

isolatedScope não tem acesso direto ao parentScope. Mas às vezes a diretiva precisa se comunicar com o parentScope. Elas se comunicam através de @, = e &. O tópico sobre o uso dos símbolos @, = e & trata de cenários usando isolatedScope.

Normalmente é usado para alguns componentes comuns compartilhados por diferentes páginas, como Modais. Um escopo isolado evita poluir o escopo global e é fácil de compartilhar entre páginas.

Aqui está uma diretiva básica: http://jsfiddle.net/7t984sf9/5/. Uma imagem para ilustrar é:

@: ligação unidirecional

@ simplesmente passa a propriedade de parentScope para isolatedScope. Isso é chamado de one-way binding (vinculação unidirecional), o que significa que você não pode modificar o valor das propriedades de parentScope. Se você estiver familiarizado com herança em JavaScript, poderá entender esses dois cenários facilmente:

  • Se a propriedade vinculada for um tipo primitivo, como interpolatedProp no exemplo: você pode modificar interpolatedProp, mas parentProp1 não seria alterada. No entanto, se você alterar o valor de parentProp1, interpolatedProp será sobrescrita com o novo valor (quando o angular $digest for executado).

  • Se a propriedade vinculada for algum objeto, como parentObj: como o que é passado para isolatedScope é uma referência, modificar o valor acionará este erro:

    TypeError: Cannot assign to read only property 'x' of {"x":1,"y":2}

=: ligação bidirecional

= é chamado de two-way binding (ligação bidirecional), o que significa que qualquer modificação em childScope também atualizará o valor em parentScope, e vice-versa. Esta regra funciona tanto para tipos primitivos quanto para objetos. Se você alterar o tipo de ligação de parentObj para =, você verá que pode modificar o valor de parentObj.x. Um exemplo típico é ngModel.

&: vinculando função

& permite que a diretiva chame alguma função do parentScope e passe algum valor da diretiva. Por exemplo, veja o JSFiddle: & no escopo da diretiva.

Defina um modelo clicável na diretiva como:

<div ng-click="vm.onCheck({valueFromDirective: vm.value + ' is from the directive'})">

E use a diretiva assim:

<div my-checkbox value="vm.myValue" on-check="vm.myFunction(valueFromDirective)"></div>

A variável valueFromDirective é passada da diretiva para o controlador pai através de {valueFromDirective: ....

Referência: Compreendendo Escopos

Resposta #3

Não é meu fiddle, mas http://jsfiddle.net/maxisam/QrCXh/ mostra a diferença. A parte chave é:

           scope:{
            /* NOTE: Normally I would set my attributes and bindings
            to be the same name but I wanted to delineate between 
            parent and isolated scope. */                
            isolatedAttributeFoo:'@attributeFoo',
            isolatedBindingFoo:'=bindingFoo',
            isolatedExpressionFoo:'&'
        }        

Resposta #4

@: ligação unidirecional

=: ligação bidirecional

&: vinculando função

Artigos relacionados