Dovrei usare `this` o` $ scope`?


251

Esistono due schemi in uso per accedere alle funzioni del controller: thise $scope.

Quale dovrei usare e quando? Capisco che thisè impostato sul controller ed $scopeè un oggetto nella catena dell'ambito per le viste. Ma con la nuova sintassi "Controller as Var", puoi facilmente usare entrambi. Quindi quello che sto chiedendo è ciò che è meglio e qual è la direzione per il futuro?

Esempio:

  1. utilizzando this

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

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

Personalmente trovo this.nameche sia più facile alla vista e più naturale rispetto ad altri modelli Javascript OO.

Consiglio per favore?


Usando 'questo' sembra essere nuova a partire dal Google I / O 2013 m.youtube.com/watch?v=HCR7i5F5L8c Inoltre, controllare questa risposta: stackoverflow.com/questions/11605917/...
Alanw

La sintassi "UserCtrl come uCtrl" è nuova? Non lo vedo documentato nelle pagine 1.0.6 o 1.1.4 ngController.
Mark Rajcok,

Va bene, è documentato sulla nuova pagina ngController 1.1.5 .
Mark Rajcok,

1
Migliori spiegazioni per $ scope e questo codetunnel.io/angularjs-controller-as-or-scope
Sai,

Risposte:


229

Entrambi hanno i loro usi. Innanzitutto, un po 'di storia ...

$ scope è la tecnica "classica", mentre "controller as" è molto più recente (a partire dalla versione 1.2.0 ufficialmente, sebbene prima apparisse in pre-release instabili).

Entrambi funzionano perfettamente bene e l'unica risposta sbagliata è mescolarli nella stessa app senza un motivo esplicito. Francamente, mescolarli funzionerà, ma aggiungerà solo confusione. Quindi scegline uno e rotola con esso. La cosa più importante è essere coerenti.

Quale? Dipende da te Ci sono molti altri esempi di $ scope, ma anche "controller as" sta prendendo piede. Uno è migliore dell'altro? È discutibile. Quindi come scegli?

Comfort

Preferisco il "controller come" perché mi piace nascondere l'ambito $ ed esporre i membri dal controller alla vista tramite un oggetto intermedio. Impostando questo. *, Posso esporre esattamente ciò che voglio esporre dal controller alla vista. Puoi farlo anche con $ scope, preferisco semplicemente usare JavaScript standard per questo. In effetti, lo codice in questo modo:

var vm = this;

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

return vm;

Questo mi sembra più pulito e rende facile vedere cosa viene esposto alla vista. Notare che ho chiamato la variabile che restituisco "vm", che sta per viewmodel. Questa è solo la mia convenzione.

Con $ scope posso fare le stesse cose, quindi non sto aggiungendo o sminuendo la tecnica.

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

Quindi tocca a te lì.

Iniezione

Con $ scope ho bisogno di iniettare $ scope nel controller. Non devo farlo con il controller come, a meno che non ne abbia bisogno per qualche altro motivo (come $ broadcast o watch, anche se cerco di evitare gli watch nel controller).

AGGIORNAMENTO Ho scritto questo post sulle 2 scelte: http://www.johnpapa.net/do-you-like-your-angular-controllers-with-or-without-sugar/


4
Personalmente seguo anche il tuo approccio usando vm. L'unico odore di codice che ho raccolto è quando devi interagire in modo specifico con $ scope, ad esempio iscrivendoti o trasmettendo eventi, accedendo a variabili di validazione dei moduli all'interno del tuo controller ecc. Questo porta ad un ambiente un po 'misto dove devi ancora iniettare $ scope anche se si utilizza il controller come funzionalità.
Oltre il

9
Destra. $ scope è ancora usato in quel caso, ma è usato più come servizio. Quando iniettiamo servizi angolari ($ scope, $ q, ecc.) Forniscono alcune funzionalità di cui abbiamo bisogno. $ scope ci consente di guardare, applicare, utilizzare i messaggi e l'associazione dei dati. E anche quando si utilizza il controller come, viene ancora utilizzato $ scope, che è appena sottratto
John Papa,

1
var vm = this;hai bisogno di chiamarlo 'vm' anche nella vista? 'controller as vm'. Devono essere uguali?
Javid

2
@JohnPapa - Perché i template di SideWaffle "return vm;" quando si utilizza Controller As?
Kevin,

2
I controller @Kevin agiscono effettivamente come Ctor e quindi restituiscono "questo" già.
John Papa,

68

$scopeviene rimosso in Angular 2.0. Pertanto, l'utilizzo thissarebbe un approccio che altri vorrebbero seguire man mano che la data di rilascio di Angular 2.0 si avvicina.


40

La mia opinione è che 'this' in javascript abbia abbastanza problemi da solo, e che l'aggiunta di un altro significato / uso per esso non sia una buona idea.

Vorrei usare $ scope, per chiarezza.

AGGIORNARE

Ora c'è la sintassi "controller as", discussa qui . Non sono un fan, ma ora che è un costrutto AngularJS più "ufficiale", merita attenzione.


10
Penso che dobbiamo prima capire la nuova sintassi "UserCtrl come uCtrl" prima di poter dire quale pensiamo sia meglio.
Mark Rajcok

Ri 'UserCtrl come uCtrl', sono d'accordo, questo deve essere compreso. Penso che sia una cattiva idea, per la maggior parte degli stessi motivi degli argomenti qui esposti
Roy Truelove,

4
Se hai familiarità con oop in JS ha perfettamente senso. Un controller è una classe e angolare utilizza il nuovo operatore ogni volta che viene creato un controller. Non vi è gradito, ma affermare che ci sono problemi con l'uso di "this" è fuorviante. È un caso d'uso accettabile per "questo".
MJ,

$ scope non aggiunge nulla alla chiarezza. In effetti, può essere molto difficile sapere cosa sta succedendo nella vista quando si usa $ scope e si hanno ambiti nidificati. Il controller come sintassi insieme all'uso di questo aggiunge molta più chiarezza. Nella vista è chiaro e chiaro da quale ambito del controller ha origine un metodo o una proprietà.
ddelrio1986,

1
Sono d'accordo con @ ddelrio1986. Ho appena avuto un problema con le schede bootstrap e agular con l'utilizzo di var vm = $ scope. Le schede hanno il loro ambito e quindi non puoi usarlo come ti aspetteresti ma con var vm = this, le cose funzionano come previsto.
user441521


7

La documentazione angolare indica esplicitamente che thissi consiglia di utilizzare . Questo, oltre al fatto che $scopeviene rimosso, è una ragione sufficiente per non usarlo mai $scope.


4

"$ scope viene rimosso in Angular 2.0" di jason328 mi sembra una buona ragione. E ho trovato un altro motivo per aiutarmi a fare la scelta: thisè più leggibile - quando vedo fooCtrl.barin HTML, so immediatamente dove trovare la definizione bar.

Aggiornamenti: non molto tempo dopo il passaggio alla thissoluzione, ho iniziato a perdere il $scopemodo in cui è necessario digitare meno


2

Preferisco una combinazione.

Un semplice console.log di $ scope e 'this' dopo averli popolati con alcuni dati falsi te lo mostreranno.

$ scope consente l'accesso alle parti sotto le coperte di un controller, ad esempio:

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

** Le proprietà e i metodi con $$ non sono raccomandati per scherzare con il team Angular, ma $ può essere un gioco sicuro per fare cose interessanti con $ parent e $ id.

'this' arriva subito al punto, allegando dati e funzioni a 2 vie. Vedrai solo ciò che hai allegato:

foo: 'bar';

Quindi perché preferisco una combinazione?

Nelle app nidificate ui-router, posso accedere al controller principale, impostare e chiamare valori e funzioni universali all'interno di un controller figlio:

Nel controller principale:

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

Nel controller bambino:

// 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;

Ora puoi accedere al genitore dall'interno del figlio e figlio dal genitore!


1

Entrambi funzionano, ma se applichi elementi appropriati per l'ambito a $ scope e se applichi elementi appropriati per il controller al controller, il tuo codice sarà facile da mantenere. Alle persone che dicono "Ugh basta usare scope dimentica questo controller come sintassi" ... Potrebbe funzionare allo stesso modo ma mi chiedo come sarai in grado di mantenere un'applicazione enorme senza perdere traccia delle cose.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.