Sintaxe de “controlador como” do AngularJ - esclarecimento?

121

Eu li sobre a nova sintaxe do angularJS sobrecontroller as xxx

A sintaxe InvoiceController as invoicediz ao Angular para instanciar o controlador e salvá-lo na fatura variável no escopo atual.

Visualização:

insira a descrição da imagem aqui

Ok, então não terei o parâmetro $scopeno meu controlador e o código será muito mais limpo no controlador.

Mas

Vou ter que especificar outro alias na view

Então até agora eu poderia fazer:

<input type="number" ng-model="qty"  />

....controller('InvoiceController', function($scope) {
   // do something with $scope.qty <--notice

E agora eu posso fazer:

 <input type="number" ng-model="invoic.qty"  /> <-- notice 

  ....controller('InvoiceController', function() {
       // do something with  this.qty  <--notice

Questão

Qual é o objetivo de fazer isso? remover de um lugar e adicionar a outro lugar?

Ficarei feliz em ver o que estou perdendo.

Royi Namir
fonte
8
Este vídeo explica muito bem. youtube.com/watch?v=tTihyXaz4Bo Acho que é usado para código mais limpo no HTML.
Fizer Khan
1
Clareza. Não estou preocupado em usar $ scope.x vs. this.x no controlador, mas, na minha opinião, vincular a {{invoice.x}} me diz mais do que apenas {{x}} (imho). Além disso, estou me perguntando se isso soluciona um problema de que ouvi falar em angular, onde não-objetos no controlador têm problemas (portanto, things.x ficaria bem, mas x causaria um problema).
Matt Roberts
1
@MattRoberts para resolver seu último comentário - o problema não-objeto que você menciona não é um problema angular, tanto quanto um fato da herança prototípica do javascript. Há uma boa explicação de por que isso acontece em angular aqui (junto com o porquê de controller ascorrigi-lo).
Russ Matney 4/04
Como vou substituir $ scope. $ Broadcast? neste novo caso, porque minha transmissão this. $ parece não estar funcionando #
Gaurav
1
@ Gaurav, você ainda pode injetar o serviço $ scope em seu controlador, mesmo se você usar o controlador como sintaxe para algumas propriedades, métodos etc.
Derek

Respostas:

163

Existem várias coisas sobre isso.

Algumas pessoas não gostam da $scopesintaxe (não me pergunte por que). Eles dizem que eles poderiam simplesmente usar this. Esse era um dos objetivos.

Deixar claro de onde vem uma propriedade também é realmente útil.

Você pode aninhar controladores e, ao ler o html, fica bem claro onde todas as propriedades vêm.

Você também pode evitar alguns dos problemas da regra de pontos .

Por exemplo, tendo dois controladores, ambos com o mesmo nome 'nome', você pode fazer isso:

<body ng-controller="ParentCtrl">
    <input ng-model="name" /> {{name}}

    <div ng-controller="ChildCtrl">
        <input ng-model="name" /> {{name}} - {{$parent.name}}
    </div>
</body>

Você pode modificar pai e filho, sem problemas. Mas você precisa usar $parentpara ver o nome do pai, porque o sombreava no controlador filho. No código html maciço $parentpode ser problemático, você não sabe de onde vem esse nome.

Com controller asvocê pode fazer:

<body ng-controller="ParentCtrl as parent">
    <input ng-model="parent.name" /> {{parent.name}}

    <div ng-controller="ChildCtrl as child">
      <input ng-model="child.name" /> {{child.name}} - {{parent.name}}
    </div>
</body>

Mesmo exemplo, mas é muito mais claro de ler.

Jesus Rodriguez
fonte
10
Também aqui é um bom exemplo de por que esta abordagem pode ser confuso para alguns: stackoverflow.com/questions/25405543/...
Julian Hollmann
Isso é muito útil quando você aninha controladores!
C_J
1
Estou tendo problemas com uma implementação semelhante de sua resposta, consulte stackoverflow.com/questions/38315538 #
587 Cody
Isso também permite que você use uma classe es6 como seu controlador e faça referência aos métodos no HTML. foo() { ... }é muito mais limpo que $scope.foo = function() { ... }.
Brian McCutchon
17

A principal vantagem da controller assintaxe que vejo é que você pode trabalhar com controladores como classes, não apenas algumas funções de decoração de escopo $ e tirar proveito da herança. Geralmente, encontro uma situação em que há uma funcionalidade muito semelhante a vários controladores, e a coisa mais óbvia a se fazer é criar uma BaseControllerclasse e herdá-la.

Embora exista uma herança $ scope, que resolve parcialmente esse problema, algumas pessoas preferem escrever código de uma maneira mais OOP, o que, na minha opinião, facilita o raciocínio e o teste do código.

Aqui está um violino para demonstrar: http://jsfiddle.net/HB7LU/5796/

Roman Kolpak
fonte
1
Isso deve ser mais positivo, já que o Fiddle é realmente útil
Mawg diz que restabelece Monica em
13

Acredito que uma vantagem específica seja clara quando você tiver escopos aninhados. Agora ficará completamente claro exatamente de que escopo uma referência de propriedade vem.

David M. Karr
fonte
7

Fonte

Diferença entre Criando um Controlador Usando o $scope objecte Usando a “controller as”Sintaxe e VM

Criando um controlador usando o objeto $ scope

Geralmente, criamos um controlador usando o objeto $ scope, como mostra a listagem abaixo:

myApp.controller("AddController", function ($scope) {



    $scope.number1;

    $scope.number2;

    $scope.result;

    $scope.add = function () {

        $scope.result = $scope.number1 + $scope.number2;

    }

});

Acima, estamos criando o AddController com três variáveis ​​e um comportamento, usando o controlador de objeto $ scope e a exibição, que se comunicam. O objeto $ scope é usado para passar dados e comportamento para a exibição. Cola a vista e o controlador juntos.

Essencialmente, o objeto $ scope executa as seguintes tarefas:

  1. Passar dados do controlador para a visualização

  2. Passar o comportamento do controlador para a visualização

  3. Cola o controlador e vê juntos

  4. O objeto $ scope é modificado quando uma exibição é alterada e uma exibição é modificada quando as propriedades do objeto $ scope são alteradas

Anexamos propriedades a um objeto $ scope para transmitir dados e comportamento à exibição. Antes de usar o objeto $ scope no controlador, precisamos passá-lo na função do controlador como dependências.

Usando a sintaxe "controller as" e vm

Podemos reescrever o controlador acima usando o controlador como sintaxe e a variável vm como mostrado na listagem abaixo:

myApp.controller("AddVMController", function () {

    var vm = this;

    vm.number1 = undefined;

    vm.number2=undefined;

    vm.result =undefined;

    vm.add = function () {

        vm.result = vm.number1 + vm.number2;

    }

});

Essencialmente, estamos atribuindo isso a uma variável vm e, em seguida, anexando uma propriedade e um comportamento a isso. Na visualização, podemos acessar o AddVmController usando o controlador como sintaxe. Isso é mostrado na lista abaixo:

<div ng-controller="AddVMController as vm">

            <input ng-model="vm.number1" type="number" />

            <input ng-model="vm.number2" type="number" />

            <button class="btn btn-default" ng-click="vm.add()">Add</button>

            <h3>{{vm.result}}</h3>

  </div>

É claro que podemos usar outro nome que não “vm” no controlador como sintaxe. Sob o capô, o AngularJS cria o objeto $ scope e anexa as propriedades e o comportamento. No entanto, usando o controlador como sintaxe, o código é muito limpo no controlador e apenas o nome alternativo é visível na exibição.

Aqui estão algumas etapas para usar o controlador como sintaxe:

  1. Crie um controlador sem o objeto $ scope.

  2. Atribua isso a uma variável local. Eu preferi o nome da variável como vm, você pode escolher qualquer nome de sua escolha.

  3. Anexe dados e comportamento à variável vm.

  4. Na exibição, forneça um alias ao controlador usando o controlador como sintaxe.

  5. Você pode atribuir qualquer nome ao alias. Prefiro usar vm, a menos que não esteja trabalhando com controladores aninhados.

Ao criar o controlador, não há vantagens diretas ou desvantagens de usar a abordagem de objeto $ scope ou o controlador como sintaxe. É apenas uma questão de escolha, no entanto, usar o controlador como sintaxe torna o código JavaScript do controlador mais legível e evita problemas relacionados a esse contexto.

Controladores aninhados na abordagem de objeto $ scope

Temos dois controladores, conforme mostrado na lista abaixo:

myApp.controller("ParentController", function ($scope) {



    $scope.name = "DJ";

    $scope.age = 32;

});

myApp.controller("ChildController", function ($scope) {



    $scope.age = 22;

    $scope.country = "India";



});

A propriedade "age" está dentro de ambos os controladores e, na exibição, esses dois controladores podem ser aninhados conforme mostrado na listagem abaixo:

<div ng-controller="ParentController">



            <h2>Name :{{name}} </h2>

            <h3>Age:{{age}}</h3>



             <div ng-controller="ChildController">

                    <h2>Parent Name :{{name}} </h2>

                    <h3>Parent Age:{{$parent.age}}</h3>

                    <h3>Child Age:{{age}}</h3>

                    <h3>Country:{{country}}</h3>

             </div>

        </div>

Como você vê, para acessar a propriedade age do controlador pai, estamos usando o $ parent.age. A separação de contexto não é muito clara aqui. Mas, usando o controlador como sintaxe, podemos trabalhar com controladores aninhados de uma maneira mais elegante. Digamos que temos controladores, conforme mostrado na listagem abaixo:

myApp.controller("ParentVMController", function () {

    var vm = this;

    vm.name = "DJ";

    vm.age = 32;

});

myApp.controller("ChildVMController", function () {

    var vm = this;

    vm.age = 22;

    vm.country = "India";



});

Na exibição, esses dois controladores podem ser aninhados, conforme mostrado na listagem abaixo:

<div ng-controller="ParentVMController as parent">



            <h2>Name :{{parent.name}} </h2>

            <h3>Age:{{parent.age}}</h3>



            <div ng-controller="ChildVMController as child">

                <h2>Parent Name :{{parent.name}} </h2>

                <h3>Parent Age:{{parent.age}}</h3>

                <h3>Child Age:{{child.age}}</h3>

                <h3>Country:{{child.country}}</h3>

            </div>

 </div>

No controlador como sintaxe, temos um código mais legível e a propriedade pai pode ser acessada usando o nome alternativo do controlador pai em vez de usar a sintaxe $ parent.

Concluirei este post dizendo que é puramente sua escolha se você deseja usar o controlador como sintaxe ou o objeto $ scope. Também não há grande vantagem ou desvantagem, simplesmente que o controlador como sintaxe que você controla no contexto é um pouco mais fácil de trabalhar, dada a clara separação nos controladores aninhados na exibição.

ShibinRagh
fonte
4

Acho que a principal vantagem é uma API mais intuitiva, pois os métodos / propriedades estão associados diretamente à instância do controlador e não ao objeto do escopo. Basicamente, com a abordagem antiga, o controlador se torna apenas uma decoração para a construção do objeto de escopo.

Aqui estão mais algumas informações sobre isso: http://www.syntaxsuccess.com/viewarticle/551798f20c5f3f3c0ffcc9ff

TGH
fonte
3

Pelo que li, $ scope será removido no Angular 2.0, ou pelo menos como vemos o uso de $ scope. Pode ser bom começar a usar o controlador assim que o lançamento do 2.0 se aproxima.

Link de vídeo aqui para mais discussões sobre o assunto.

jason328
fonte