Devo usar `this` ou` $ scope`?

251

Existem dois padrões em uso para acessar as funções do controlador: thise $scope.

Qual devo usar e quando? Eu entendo thisé definido como o controlador e $scopeé um objeto na cadeia de escopo de visualizações. Mas com a nova sintaxe "Controller as Var", você também pode usar facilmente. Então, o que estou perguntando é o que é melhor e qual é a direção para o futuro?

Exemplo:

  1. Usando this

    function UserCtrl() {
      this.bye = function() { alert('....'); };
    }
    <body ng-controller='UserCtrl as uCtrl'>
      <button ng-click='uCtrl.bye()'>bye</button>
  2. Usando $scope

    function UserCtrl($scope) {
        $scope.bye = function () { alert('....'); };
    }
    <body ng-controller='UserCtrl'>
        <button ng-click='bye()'>bye</button>

Pessoalmente, acho this.nameque é mais fácil para os olhos e mais natural em comparação com outros padrões de Javascript OO.

Conselho por favor?

SenseDeep
fonte
O uso de 'this' parece ser novo a partir do Google I / O 2013 m.youtube.com/watch?v=HCR7i5F5L8c Além disso, verifique esta resposta: stackoverflow.com/questions/11605917/…
AlanW
A sintaxe "UserCtrl as uCtrl" é nova? Não o vejo documentado nas páginas 1.0.6 ou 1.1.4 ngController.
Mark Rajcok
Ok, está documentado na nova página do 1.1.5 ngController .
Mark Rajcok
1
Melhores explicações para $ âmbito e este codetunnel.io/angularjs-controller-as-or-scope
Sai

Respostas:

229

Ambos têm seus usos. Primeiro, um pouco de história ...

$ scope é a técnica "clássica", enquanto "controller as" é muito mais recente (a partir da versão 1.2.0 oficialmente, embora ela tenha aparecido em pré-lançamentos instáveis ​​anteriores a isso).

Ambos funcionam perfeitamente bem e a única resposta errada é misturá-los no mesmo aplicativo sem uma razão explícita. Francamente, misturá-los funcionará, mas isso apenas aumentará a confusão. Então escolha um e role com ele. O mais importante é ser consistente.

Qual? Isso depende de você. Existem muitos outros exemplos no escopo $, mas "controller as" também está ganhando força. Um é melhor que o outro? Isso é discutível. Então como você escolhe?

Conforto

Prefiro o "controller as" porque gosto de ocultar o escopo $ e expor os membros do controller à visualização por meio de um objeto intermediário. Ao definir isso. *, Posso expor exatamente o que quero expor do controlador para a exibição. Você também pode fazer isso com $ scope, apenas prefiro usar JavaScript padrão para isso. Na verdade, eu codifico assim:

var vm = this;

vm.title = 'some title';
vm.saveData = function(){ ... } ;

return vm;

Isso me parece mais limpo e facilita ver o que está sendo exposto à vista. Observe que eu nomeio a variável que retorno "vm", que significa viewmodel. Essa é apenas a minha convenção.

Com $ scope eu posso fazer as mesmas coisas, então não estou adicionando ou prejudicando a técnica.

$scope.title = 'some title';
$scope.saveData = function() { ... };

Então cabe a você lá.

Injeção

Com $ scope, eu preciso injetar $ scope no controlador. Não preciso fazer isso com o controlador, a menos que precise por algum outro motivo (como $ broadcast ou relógios, embora tente evitar relógios no controlador).

ATUALIZAÇÃO Escrevi este post sobre as 2 opções: http://www.johnpapa.net/do-you-like-your-angular-controllers-with-or-without-sugar/

John Papa
fonte
4
Pessoalmente, também sigo sua abordagem usando vm. O único cheiro de código que percebi é quando você precisa interagir especificamente com $ scope, por exemplo, assinar ou transmitir eventos, acessar variáveis ​​de validação de formulário dentro de seu controlador etc. Isso leva a um ambiente um tanto misto, no qual você ainda precisa injetar $ scope mesmo que você use o controlador como recurso.
quer
9
Certo. $ scope ainda é usado nesse caso, mas é usado mais como um serviço. Quando injetamos serviços angulares ($ scope, $ q, etc), eles fornecem algum recurso que precisamos. O $ scope nos permite assistir, aplicar, usar mensagens e vincular dados. E mesmo quando usando o controlador como, $ âmbito ainda é usado, é apenas abstraída
John Papa
1
var vm = this;você também precisa chamá-lo de 'vm'? 'controlador como vm'. Eles têm que ser iguais?
Javid
2
@JohnPapa - Por que os modelos do SideWaffle "não retornam vm;" ao usar o controlador como?
Kevin
2
Os controladores @ Kevin atuam efetivamente como um Ctor e, assim, retornam "isso" já.
John Papa
68

$scopeestá sendo removido no Angular 2.0. Portanto, usar thisseria uma abordagem que outros desejam seguir à medida que a data de lançamento do Angular 2.0 se aproxima.

jason328
fonte
40

Minha opinião é que 'this' em javascript tem problemas suficientes por si só, e que adicionar outro significado / uso não é uma boa ideia.

Eu usaria $ scope, por uma questão de clareza.

ATUALIZAR

Agora existe a sintaxe 'controller as', discutida aqui . Não sou fã, mas agora que é uma construção AngularJS mais 'oficial', ela merece alguma atenção.

Roy Truelove
fonte
10
Acho que primeiro precisamos entender a nova sintaxe "UserCtrl as uCtrl" antes de podermos dizer o que achamos melhor.
22813 Mark Rajcok
Re 'UserCtrl como uCtrl', eu concordo, isso precisa ser entendido. Eu acho que é uma má ideia, para a maioria das mesmas razões que os argumentos feitos aqui: groups.google.com/forum/#!topic/angular/84selECbp1I
Roy Truelove
4
Se você está familiarizado com oop em JS , faz todo o sentido. Um controlador é uma classe e angular usa o novo operador sempre que um controlador é criado. Você pode não gostar, mas afirmar que há problemas com o uso de 'this' é enganoso. É um caso de uso aceitável para 'this'.
MJ
$ scope não acrescenta nada à clareza. De fato, pode ser muito difícil saber o que está acontecendo na exibição ao usar $ scope e você tem escopos aninhados. O controlador como sintaxe, juntamente com o uso disso, adiciona muito mais clareza. Na visão, é bom e claro de qual escopo do controlador um método ou propriedade se origina.
ddelrio1986
1
Eu concordo com @ ddelrio1986. Apenas tive um problema com as guias de inicialização e agular com o uso de var vm = $ scope. As guias têm seu próprio escopo e, portanto, você não pode usá-lo como seria de esperar, mas com var vm = this, tudo funciona como esperado.
user441521
11

Eu acho que o Controller As é melhor, pois permite aninhar escopos mais facilmente, conforme descrito por Todd Motto aqui:

http://toddmotto.com/digging-into-angulars-controller-as-syntax/

Além disso, garantirá que você sempre tenha pelo menos um. na sua expressão de ligação, que força você a seguir a recomendação não vincular às primitivas .

Além disso, você pode se separar do escopo que está desaparecendo no 2.0.

Ryan Vice
fonte
7

A documentação angular informa explicitamente que o uso thisé recomendado. Isso, além do fato de $scopeestar sendo removido, é motivo suficiente para eu nunca usar $scope.

tjespe
fonte
4

"O escopo $ de jason328 está sendo removido no Angular 2.0" parece um bom motivo para mim. E encontrei outro motivo para me ajudar a fazer a escolha: thisé mais legível - quando vejo fooCtrl.barem HTML, imediatamente sei onde encontrar a definição de bar.

Atualizações: pouco tempo depois de mudar para a thissolução, comecei a perder o $scopecaminho que precisa de menos digitação

ZZY
fonte
2

Eu prefiro uma combinação.

Um console.log simples de $ scope e 'this' depois de preenchê-los com alguns dados simulados mostrarão isso.

$ scope permite o acesso às partes inferiores de um controlador, por exemplo:

$$ChildScope: null;
$$childHead: null;
$$childTail: null;
$$listenerCount: Object;
$$listeners: Object;
$$nextSibling: Scope;
$$prevSibling: null;
$$watchers: null;
$$watcherCount: 0;
$id: 2;
$parent: Object;
foo: 'bar';

** Propriedades e métodos com $$ não são recomendados para a equipe Angular, mas o $ pode ser um jogo seguro para fazer coisas legais com $ parent e $ id.

'this' vai direto ao ponto, anexando dados e funções com duas direções. Você verá apenas o que anexou:

foo: 'bar';

Então, por que prefiro uma combinação?

Nos aplicativos aninhados do ui-router, eu posso acessar o controlador principal, definir e chamar valores e funções universais dentro de um controlador filho:

No controlador principal:

// Main Controller
var mainCtrl = this;
mainCtrl.foo = 'Parent at the bar';

No controlador infantil:

// Child Controller
var mainCtrl = $scope.$parent.mainCtrl;
var childCtrl = this;

// update the parent from within the child
childCtrl.underageDrinking = function(){
    mainCtrl.foo = 'Child at the bar';
}

// And then attach the child back to a property on the parent controller!
mainCtrl.currentCtrl = childCtrl;

Agora, você pode acessar o pai de dentro do filho e o filho do pai!

Craig O. Curtis
fonte
1

Ambos funcionam, mas se você aplicar coisas apropriadas para o escopo em $ scope, e se você aplicar coisas apropriadas para o controlador no controlador, seu código será fácil de manter. Para as pessoas que dizem "Ugh, use apenas o escopo, esqueça este controlador como sintaxe" ... Pode funcionar da mesma forma, mas eu me pergunto como você conseguirá manter um aplicativo enorme sem perder o controle das coisas.

Nick Manning
fonte