Dois-je utiliser «this» ou «$ scope»?

251

Il existe deux modèles utilisés pour accéder aux fonctions du contrôleur: thiset $scope.

Que dois-je utiliser et quand? Je comprends thisest défini sur le contrôleur et $scopeest un objet dans la chaîne de portée pour les vues. Mais avec la nouvelle syntaxe "Controller as Var", vous pouvez facilement utiliser l'une ou l'autre. Alors ce que je demande, c'est ce qui est le mieux et quelle est la direction pour l'avenir?

Exemple:

  1. En utilisant this

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

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

Personnellement, je trouve this.namecela plus agréable à l'œil et plus naturel par rapport aux autres modèles Javascript OO.

Des conseils s'il vous plait?

SenseDeep
la source
L'utilisation de «ceci» semble être nouvelle depuis Google I / O 2013 m.youtube.com/watch?v=HCR7i5F5L8c Vérifiez également cette réponse: stackoverflow.com/questions/11605917/…
AlanW
La syntaxe "UserCtrl as uCtrl" est-elle nouvelle? Je ne le vois pas documenté sur les pages 1.0.6 ou 1.1.4 ngController.
Mark Rajcok
D'accord, il est documenté sur la nouvelle page 1.1.5 ngController .
Mark Rajcok
1
Meilleures explications pour $ scope et ce codetunnel.io/angularjs-controller-as-or-scope
Sai

Réponses:

229

Les deux ont leur utilité. Tout d'abord, un peu d'histoire ...

$ scope est la technique "classique" tandis que "controller as" est beaucoup plus récent (à partir de la version 1.2.0 officiellement bien qu'il apparaissait dans les pré-versions instables avant cela).

Les deux fonctionnent parfaitement bien et la seule mauvaise réponse est de les mélanger dans la même application sans raison explicite. Franchement, les mélanger fonctionnera, mais cela ne fera qu'ajouter à la confusion. Alors choisissez-en un et roulez avec. La chose la plus importante est d'être cohérent.

Laquelle? Cela dépend de vous. Il existe de nombreux autres exemples de $ scope, mais "controller as" prend également de l'ampleur. Est-ce que l'un est meilleur que l'autre? C'est discutable. Alors, comment choisissez-vous?

Confort

Je préfère le "contrôleur en tant que" car j'aime cacher la portée $ et exposer les membres du contrôleur à la vue via un objet intermédiaire. En définissant ceci. *, Je peux exposer exactement ce que je veux exposer du contrôleur à la vue. Vous pouvez le faire avec $ scope aussi, je préfère simplement utiliser JavaScript standard pour cela. En fait, je le code comme ceci:

var vm = this;

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

return vm;

Cela me semble plus propre et permet de voir facilement ce qui est exposé à la vue. Remarquez que je nomme la variable que je renvoie "vm", qui signifie viewmodel. C'est juste ma convention.

Avec $ scope, je peux faire les mêmes choses, donc je n'ajoute ni n'altère la technique.

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

Donc, c'est à vous là-bas.

Injection

Avec $ scope, j'ai besoin d'injecter $ scope dans le contrôleur. Je n'ai pas à le faire avec le contrôleur car, sauf si j'en ai besoin pour une autre raison (comme $ broadcast ou montres, bien que j'essaie d'éviter les montres dans le contrôleur).

MISE À JOUR J'ai écrit cet article sur les 2 choix: http://www.johnpapa.net/do-you-like-your-angular-controllers-with-or-without-sugar/

John Papa
la source
4
Personnellement, je suis également votre approche en utilisant vm. La seule odeur de code que j'ai détectée est lorsque vous devez interagir spécifiquement avec $ scope, par exemple en vous abonnant ou en diffusant des événements, en accédant à des variables de validation de formulaire à l'intérieur de votre contrôleur, etc. Cela conduit à un environnement quelque peu mixte où vous devez toujours injecter $ scope même si vous utilisez le contrôleur comme fonctionnalité.
Beyers
9
Droite. $ scope est toujours utilisé dans ce cas, mais il est davantage utilisé en tant que service. Lorsque nous injectons des services angulaires ($ scope, $ q, etc.), ils fournissent certaines fonctionnalités dont nous avons besoin. $ scope nous permet de surveiller, d'appliquer, d'utiliser des messages ainsi que la liaison de données. Et même lorsque vous utilisez le contrôleur en tant que, $ scope est toujours utilisé, c'est juste résumé
John Papa
1
var vm = this;devez-vous également l'appeler "vm" dans la vue? 'contrôleur en tant que vm'. Doivent-ils être les mêmes?
Javid
2
@JohnPapa - Pourquoi les modèles SideWaffle ne "renvoient-ils pas vm;" lors de l'utilisation de Controller As?
Kevin
2
Les contrôleurs @Kevin agissent effectivement comme un Ctor et retournent donc déjà "this".
John Papa
68

$scopeest en cours de suppression dans Angular 2.0. Ainsi, l'utilisation thisserait une approche que d'autres voudraient suivre à mesure que la date de sortie d'Angular 2.0 se rapproche.

jason328
la source
40

Mon opinion est que «ceci» en javascript a suffisamment de problèmes en soi, et que l'ajout d'une autre signification / utilisation n'est pas une bonne idée.

J'utiliserais $ scope, par souci de clarté.

METTRE À JOUR

Il y a maintenant la syntaxe «contrôleur en tant que», discutée ici . Je ne suis pas fan, mais maintenant que c'est une construction AngularJS plus «officielle», elle mérite une certaine attention.

Roy Truelove
la source
10
Je pense que nous devons d'abord comprendre la nouvelle syntaxe "UserCtrl as uCtrl" avant de pouvoir dire laquelle nous pensons être la meilleure.
Mark Rajcok
Re 'UserCtrl as uCtrl', je suis d'accord, cela doit être compris. Je pense que c'est une mauvaise idée, pour la plupart des mêmes raisons que les arguments avancés ici: groups.google.com/forum/#!topic/angular/84selECbp1I
Roy Truelove
4
Si vous êtes familier avec oop dans JS, cela est parfaitement logique. Un contrôleur est une classe et angulaire utilise le nouvel opérateur chaque fois qu'un contrôleur est créé. Vous êtes invités à ne pas l'aimer, mais déclarer qu'il y a des problèmes avec l'utilisation de «ceci» est trompeur. Il s'agit d'un cas d'utilisation acceptable pour «ceci».
MJ
$ scope n'ajoute rien à la clarté. En fait, il peut être très difficile de savoir ce qui se passe dans la vue lorsque vous utilisez $ scope et que vous avez des étendues imbriquées. Le contrôleur en tant que syntaxe et son utilisation ajoutent beaucoup plus de clarté. Dans la vue, il est clair et clair de quelle portée de contrôleur provient une méthode ou une propriété.
ddelrio1986
1
Je suis d'accord avec @ ddelrio1986. Je viens d'avoir un problème avec les onglets bootstrap et agular avec l'utilisation de var vm = $ scope. Les onglets ont leur propre portée et vous ne pouvez donc pas l'utiliser comme vous vous y attendez, mais avec var vm = this, les choses fonctionnent comme prévu.
user441521
11

Je pense que Controller As est meilleur car il permet d'imbriquer plus facilement les étendues décrites par Todd Motto ici:

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

De plus, cela vous assurera d'en avoir toujours au moins un. dans votre expression de liaison qui vous oblige à suivre la recommandation de ne pas vous lier aux primitives .

De plus, vous pouvez vous dissocier de la portée qui disparaît dans 2.0.

Ryan Vice
la source
7

La documentation Angular vous indique explicitement que l'utilisation thisest recommandée. Cela, en plus du fait qu'il $scopeest supprimé, est une raison suffisante pour que je ne l'utilise jamais $scope.

tjespe
la source
4

"La portée de $ de jason328 est supprimée dans Angular 2.0" me semble être une bonne raison. Et j'ai trouvé une autre raison pour m'aider à faire le choix: thisest plus lisible - quand je vois fooCtrl.baren HTML, je sais immédiatement où trouver la définition debar .

Mises à jour: peu de temps après le passage à la thissolution, j'ai commencé à manquer un $scopemoyen qui nécessite moins de frappe

ZZY
la source
2

Je préfère une combinaison.

Un simple console.log de $ scope et «ceci» après les avoir remplis avec des données factices vous le montrera.

$ scope permet d'accéder aux parties sous les couvertures d'un contrôleur, par exemple:

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

** Les propriétés et les méthodes avec $$ ne sont pas recommandées par l'équipe Angular, mais le $ peut être un jeu sûr pour faire des trucs sympas avec $ parent et $ id.

'ceci' va droit au but, en attachant des données et des fonctions à double sens. Vous ne verrez que ce que vous avez joint:

foo: 'bar';

Alors pourquoi je préfère une combinaison?

Dans les applications imbriquées ui-router, je peux accéder au contrôleur principal, définir et appeler des valeurs et des fonctions universelles à l'intérieur d'un contrôleur enfant:

Dans le contrôleur principal:

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

Dans le contrôleur enfant:

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

Maintenant, vous pouvez accéder au parent de l'enfant et à l'enfant du parent!

Craig O. Curtis
la source
1

Les deux fonctionnent, mais si vous appliquez des éléments appropriés pour l'étendue à $ scope, et si vous appliquez des éléments appropriés pour le contrôleur au contrôleur, votre code sera facile à maintenir. Aux personnes qui disent "Ugh, utilisez simplement la portée, oubliez ce contrôleur comme syntaxe" ... Cela peut fonctionner de la même manière, mais je me demande comment vous pourrez maintenir une énorme application sans perdre la trace des choses.

Nick Manning
la source