angularjs - directive restrict c




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

Por que preciso usar "{{title}}" com " @ " e "title" com " = "?

@ liga uma propriedade de escopo local / diretiva ao valor avaliado do atributo DOM . Se você usar title=title1 ou 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 de escopo pai "title" atualmente definida como. Como os valores dos atributos são sempre strings, você sempre terminará com 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 do 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}} são interpoladas, então a string "e algumas delas" é concatenada com ele. A cadeia final concatenada é o que a propriedade do escopo local / diretivo 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 esse atributo de asynchronously . 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 apenas se você não usar um escopo isolado. Remova esta linha da sua diretiva

scope: { ... }

e, em seguida, 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 parece funcionar bem com a vinculação bidirecional também. Por que a rota da expressão seria melhor?

Sim, a ligação bidirecional permite que o escopo local / diretivo e o escopo pai compartilhem dados. "Expression binding" 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. Então, se você não precisa compartilhar dados com o pai - você só quer chamar uma função definida no escopo pai - você pode usar a sintaxe.

Veja também

Eu li a documentação do AngularJS sobre o tópico com cuidado e, em seguida, procurei uma diretiva. Aqui está o fiddle .

E aqui estão alguns trechos relevantes:

  • Do HTML:

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

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

Existem várias coisas que não entendo:

  • Por que preciso 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 por meio de uma expressão e para o escopo pai" , mas isso parece funcionar bem com a vinculação bidirecional também. Por que a rota da expressão seria melhor?

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


Por que preciso usar "{{title}}" com "@" e "title" com "="?

Quando você usa {{title}}, somente o valor do escopo pai será passado para a visualização diretiva e avaliado. Isso é limitado a um caminho, o que significa que a mudança não será refletida no escopo pai. Você pode usar '=' quando quiser também refletir as alterações feitas na diretiva child para o escopo pai. Isso é de dois modos.

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

Quando a diretiva possui um atributo scope (escopo: {}), você não poderá mais acessar o escopo pai diretamente. Mas ainda é possível acessá-lo via escopo. $ Pai etc. Se você remover o escopo da diretiva, ele pode 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 parece funcionar bem com a vinculação bidirecional também. Por que a rota da expressão seria melhor?

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

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

AngularJS - escopos isolados - @ vs = vs &

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


@ 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 de sua diretiva, de modo que possa ser chamado dentro de sua diretiva.

@ Vinculação de cadeia de atributos = Ligação de modelo bidirecional e vinculação de método de retorno de chamada


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>

Existem três maneiras de o escopo ser adicionado na diretiva:

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

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

  1. Escopo filho : 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, ele não será refletido no escopo pai, mas se você alterar a propriedade de uma variável de escopo, isso é refletido no escopo pai, como 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ê está criando plugins, pois isso torna a diretiva genérica, já que ela pode ser colocada em qualquer HTML e não é afetada por seu escopo pai.

Agora, se você não quiser nenhuma interação com o escopo pai, poderá simplesmente especificar o escopo como um objeto vazio. gostar,

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

Principalmente, este não é o caso, pois precisamos de alguma interação com o escopo pai, então queremos que alguns dos valores / mudanças passem. 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 do escopo do controlador serão refletidas no escopo da diretiva, mas se você modificar o valor no escopo da diretiva, a variável de 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 envolver o valor do atributo dentro de {{}}.

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

& é usado para ligar o método do escopo do controlador, de modo que, se necessário, podemos 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.

Exemplo, o escopo da diretiva tem uma variável "dirVar" que sincroniza com a variável "contVar" do escopo do controlador. Isso dá muita potência e generalização à diretiva, já que um controlador pode sincronizar com a variável v1, enquanto outro controlador, usando a mesma diretiva, pode pedir ao dirVar para sincronizar 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 (note a diferença para @ e =):

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

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


Há muitas ótimas respostas aqui, mas gostaria de oferecer minha perspectiva sobre as diferenças entre @ , = e & binding que se mostraram úteis para mim.

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

  1. @ binding é para passar strings. Essas cadeias 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 é vinculado ao modelo no escopo isolado da diretiva. Mudanças em um modelo afetam o outro e vice-versa.

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

Eu acho que é mais fácil lembrar dessas diferenças referindo-se às ligações de escopo por uma descrição mais curta:

  • @ Ligação de cadeia de atributos
  • = Ligação de modelo bidirecional
  • Ligação ao 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:

  • @ string
  • = model
  • & método

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

  1. =
  2. @
  3. E

O = significa ligação bidirecional, portanto, 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) para a 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 a partir da diretiva (ou passar dados por meio de um serviço).


O caminho = é de 2 vias , o que permite que você tenha alterações ao vivo dentro de sua diretiva. Quando alguém altera essa variável para fora da diretiva, você terá esses dados alterados dentro de sua diretiva, mas o @way não é vinculação de duas vias . Funciona como texto . Você liga uma vez e só terá seu valor.

Para obter mais clareza, você pode usar este ótimo artigo:

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


Simplesmente podemos usar: -

  1. @ : - para valores de string para ligação de dados unidirecional. de uma forma de ligação de dados você só pode passar o valor do escopo para 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, bem como no html também.

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

EDITAR

Na nossa definição de componente para Angular versão 1.5 e acima
Existem quatro tipos diferentes de ligações:

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

  3. @ isto é para os parâmetros de string

  4. & isto é para Callbacks no caso de seu componente precisar gerar algo para seu escopo pai


a principal diferença entre eles é apenas

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

@ e = veja outras respostas.

Um gotcha sobre &
TL; DR;
& Obtém expressão (não apenas funciona como nos exemplos em outras respostas) de um pai, e define como uma função na diretiva, que chama a expressão. E essa função tem a capacidade de substituir qualquer variável (até nome da função) da expressão, passando um objeto com as variáveis.

explicado
& é 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} .
então, no html da diretiva <button ng-click="expr()"></button> chamará a expressão. Em js da diretiva apenas $scope.expr() chamará a expressão também.
A expressão será chamada com $ scope.x e $ scope.y do pai.
Você tem a capacidade de substituir os parâmetros!
Se você configurá-los por chamada, por exemplo, <button ng-click="expr({x:5})"></button>
então a expressão será chamada com o seu parâmetro x e o parâmetro do pai y .
Você pode substituir os dois.
Agora você sabe, porque <button ng-click="functionFromParent({x:5})"></button> funciona.
Porque ele 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 chamada de criança:
<button ng-click="functionFromParent({x:5, z: 4})"></button> .
ou até mesmo com 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> chama $scope.x==$scope.y
<button ng-click="expr({x: 5})"></button> chama 5 == $scope.y
<button ng-click="expr({x:5, y:6})"></button> chama 5 == 6

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

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


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

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

A propriedade de escopo local permite ao consumidor de uma diretiva passar uma função que a diretiva pode invocar.

Por favor, verifique o link abaixo, que lhe dá uma compreensão clara com exemplos.Eu achei muito útil, então pensei em compartilhá-lo.

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





isolated-scope