'cette' vs $portée dans AngularJS contrôleurs
Dans le "Créer des Composants" section de la page d'accueil de AngularJS, il y a cet exemple:
controller: function($scope, $element) {
var panes = $scope.panes = [];
$scope.select = function(pane) {
angular.forEach(panes, function(pane) {
pane.selected = false;
});
pane.selected = true;
}
this.addPane = function(pane) {
if (panes.length == 0) $scope.select(pane);
panes.push(pane);
}
}
Remarquez comment le select
méthode est ajoutée à $scope
, mais le addPane
méthode est ajoutée à this
. Si je l'ai changer pour $scope.addPane
, le code des pauses.
La documentation indique qu'il y a en fait une différence, mais il ne mentionne pas quelle est la différence:
Les versions précédentes Angulaire (pré 1.0 RC) vous a permis d'utiliser
this
de façon interchangeable avec le$scope
méthode, mais ce n'est plus le cas. À l'intérieur des méthodes définies dans le champ d'applicationthis
et$scope
sont interchangeables (angulaire fixethis
à$scope
), mais pas le contraire à l'intérieur de votre contrôleur de constructeur.
Comment this
et $scope
travail dans AngularJS contrôleurs?
C'est que confusion à propos de "les versions Précédentes..." a été retiré par maintenant? Alors peut-être mise à jour devrait être en place?
Pour les tests unitaires, si vous utilisez la "cela" au lieu de "$champ d'application", vous ne pouvez pas injecter le contrôleur avec un moqué de portée, et vous ne pouvez pas faire les tests unitaires. Je ne pense pas que c'est une bonne pratique à utiliser "il".
OriginalL'auteur Alexei Boronine | 2012-07-23
Vous devez vous connecter pour publier un commentaire.
Réponse courte:
this
this
est le contrôleur.$scope
objet est appelé,this
est le "champ d'application en vigueur au moment où la fonction a été appelée". Cela peut (ou pas!) être le$scope
que la fonction est définie sur. Ainsi, à l'intérieur de la fonction,this
et$scope
peut pas être le même.$scope
$scope
objet.$scope
.$scope
objet (et de la portée parent objets, si l'héritage par prototype est en jeu) sont accessibles à partir de pages HTML/vue. E. g., deng-click
, filtres, etc.Réponse longue:
Un contrôleur de fonction est une fonction constructeur de JavaScript. Lorsque le constructeur de la fonction exécute (par exemple, lorsqu'une vue de charges),
this
(c'est à dire, la fonction de "contexte") est définie pour l'objet contrôleur. Ainsi, dans les "onglets" contrôleur de fonction constructeur, lorsque le addPane fonction est crééeil est créé sur le contrôleur de l'objet, pas sur $champ d'application. Les vues ne peut pas voir la addPane fonction -- ils ont seulement accès à des fonctions définies sur $champ d'application. En d'autres termes, dans le code HTML, cela ne fonctionne pas:
Après les "onglets" contrôleur constructeur de la fonction s'exécute, nous avons les éléments suivants:
La ligne noire en pointillés indique prototypes héritage -- un isolat portée fait hérite de Portée. (Il n'a pas fait hériter de la portée en effet, lorsque la directive a été rencontrée dans le code HTML.)
Maintenant, le volet de la directive en fonction de lien veut communiquer avec les onglets de la directive (ce qui signifie vraiment qu'il doit affecter les onglets isoler $portée en quelque sorte). Les événements peuvent être utilisés, mais d'un autre mécanisme est d'avoir le volet de la directive
require
les onglets contrôleur. (Il semble y avoir aucun mécanisme pour le volet de la directive derequire
les onglets $l'étendue).Donc, cela pose la question: si nous avons seulement accès aux onglets de contrôleur, comment pouvons-nous obtenir l'accès aux onglets isoler $scope (qui est ce que nous voulons vraiment)?
Bien, la ligne pointillée rouge est la réponse. Le addPane() de la fonction de "champ" (je fais référence à JavaScript de la portée de la fonction/fermetures ici) donne la fonction d'accès aux onglets isoler $champ d'application. I. e., addPane() a accès à la "onglets IsolateScope" dans le diagramme ci-dessus en raison d'une fermeture qui a été créé lors de addPane() a été défini. (Si nous l'avons défini à l'addPane() sur les onglets $objet de l'étendue, le volet de la directive n'aurait pas accès à cette fonction, et donc il n'aurait aucun moyen de communiquer avec les onglets $l'étendue).
Pour répondre à l'autre partie de votre question:
how does $scope work in controllers?
:À l'intérieur des fonctions définies sur $portée,
this
est réglé sur "le $scope en effet où/quand la fonction a été appelée". Supposons que nous avons le code HTML suivant:Et la
ParentCtrl
(Uniquement) aEn cliquant sur le premier lien montrera que
this
et$scope
sont les mêmes, car "le champ d'application en vigueur au moment où la fonction a été appelée" est le champ associé à laParentCtrl
.Cliquant sur le deuxième lien révéler
this
et$scope
sont pas le même, puisque "le champ d'application en vigueur au moment où la fonction a été appelée" est le champ associé à laChildCtrl
. Donc, ici,this
est fixé àChildCtrl
's$scope
. À l'intérieur de la méthode,$scope
est toujours leParentCtrl
's $scope.Violon
J'essaie de ne pas utiliser
this
à l'intérieur d'une fonction définie sur $champ d'application, car il devient confus dollars, dont la portée est affecté, d'autant plus que ng-repeat, ng-inclure, ng-switch, et les directives peuvent tous créer leur propre enfant étendues.Notez qu'il est maintenant possible d'appeler la addPane() fonction directement dans le modèle de nommage le contrôleur: "MyController comme myctrl" et puis myctrl.addPane(). Voir docs.angularjs.org/guide/concepts#controller
Trop de complexité inhérente.
C'est une très instructif de réponse, mais quand je suis de retour avec un problème pratique (comment appeler $scope.$appliquer() dans un contrôleur de la méthode définie à l'aide de 'cette'), je ne pouvais pas travailler. Donc, même si c'est encore une réponse utile, je viens de trouver la "complexité" déroutante.
Javascript - beaucoup de corde [pour vous accrocher].
OriginalL'auteur Mark Rajcok
La raison "addPane" est attribué à ce est en raison de la
<pane>
directive.La
pane
directive nerequire: '^tabs'
, qui met les onglets objet de contrôleur de la part d'un parent de la directive, dans la fonction de lien.addPane
est attribué àthis
de sorte que lepane
fonction de lien pouvez le voir. Puis, dans lapane
fonction de lien,addPane
est juste une propriété de latabs
contrôleur, et c'est juste tabsControllerObject.addPane. Ainsi, le volet de la directive en fonction de liaison pouvez accéder aux onglets du contrôleur de l'objet et, par conséquent, l'accès à la addPane méthode.J'espère que mon explication est assez claire.. c'est un peu difficile à expliquer.
Il semble que le parent n'est pas passé dans le lnk func en raison de la volonté de soutenir des "composants réutilisables, ce qui ne devrait pas accidentellement lire ou modifier des données dans la portée parent." Mais si une directive n'a vraiment envie/besoin de lire ou modifier des données SPÉCIFIQUES dans la portée parent (comme le 'volet' directive n'), il nécessite un certain effort: "requiert" le contrôleur lorsque le parent voulu champ d'application est, puis de définir une méthode sur l'autre contrôleur (utiliser " il " et non pas $champ) pour accéder à des données spécifiques. Depuis le désiré parent n'est pas injecté dans le lnk func, je suppose que c'est la seule façon de le faire.
Hey, c'est effectivement plus facile de modifier la directive. Il vous suffit d'utiliser la fonction de lien jsfiddle.net/TuNyj
Merci @Andy pour le violon. Dans votre violon, la directive n'est pas de la création d'un nouveau champ d'application, afin que je puisse voir comment la fonction de lien peut accéder directement au contrôleur du champ d'application ici (car il n'y a qu'un seul champ). Les onglets et volet directives d'utilisation isoler étendues (c'est à dire, les nouvelles de l'enfant étendues sont créés ne fait hériter de la portée parent). Pour l'isoler de la portée de cas, il semble que la définition d'une méthode sur un contrôleur (en utilisant "il") est la seule façon de permettre à un autre de la directive pour obtenir (indirecte) de l'accès à l'autre (isolé) champ d'application.
OriginalL'auteur Andrew Joslin
Je viens de lire un très intéressant explication sur la différence entre les deux, et une augmentation de la préférence pour attacher des modèles pour le contrôleur d'alias et le contrôleur de lier les modèles de la vue. http://toddmotto.com/digging-into-angulars-controller-as-syntax/ est l'article. Il ne parle pas, mais lors de la définition des directives, si vous avez besoin de partager quelque chose entre plusieurs directives et ne veulent pas d'un service (il y a de légitime cas où les services sont une corvée) fixez ensuite les données à la mère de la directive du contrôleur. Le $scope service offre beaucoup de choses utiles, $montre le plus évident, mais si tout ce que vous devez lier des données à la vue, à l'aide de la plaine contrôleur et le contrôleur que dans le modèle est très bien, et sans doute préférable.
OriginalL'auteur Derek
Je vous recommande de lire le post suivant:
AngularJS: "Contrôleur" ou "$champ d'application"?
Il décrit très bien les avantages de l'utilisation de "Contrôleur" pour exposer des variables sur "$champ d'application".
Je sais que vous avez demandé spécifiquement sur les méthodes et les pas des variables, mais je pense que c'est mieux de s'en tenir à une technique et d'être en accord avec elle.
Donc, à mon avis, parce que les variables du problème abordé dans le post, il est préférable de n'utiliser que le "Contrôleur" de la technique et de l'appliquer aussi à l'méthodes.
OriginalL'auteur Liran Brimer
Dans ce cours(https://www.codeschool.com/courses/shaping-up-with-angular-js) ils expliquent comment utiliser "ce" et beaucoup d'autres choses.
Si vous ajouter une méthode pour le contrôleur à travers "cette" méthode, il faut l'appeler dans la vue à l'aide du contrôleur nom "dot" de votre propriété ou de la méthode.
Par exemple à l'aide de votre contrôleur de la vue, vous pouvez avoir un code comme ceci:
$scope
, donc merci de le mentionner.Ce cours ne fait pas mention de $portée de tous, ils utilisent la
as
etthis
alors, comment peut-il aider à expliquer la différence?Mon premier contact avec Angulaire est à partir de la cours, et que
$scope
n'a jamais été évoqué, j'ai appris à utiliser justethis
dans les contrôleurs. Le problème est que lorsque vous commencez à avoir tohandle promesses dans votre contrôleur, vous avez beaucoup de références problème dethis
et avez pour commencer à faire des choses commevar me = this
pour référence le modèle dansthis
de l'intérieur de la promesse de retour de la fonction. Donc à cause de cela, je suis encore très confus au sujet de la méthode à me$scope
outhis
.Malheureusement, vous aurez besoin
var me = this
ou.bind(this)
chaque fois que vous faites des Promesses, ou d'autres la fermeture du lourd. Il n'a rien à voir avec Angulaire.L'important est de savoir que
ng-controller="MyCtrl as MC"
est équivalent à la mise$scope.MC = this
dans le contrôleur lui-même -- il définit une instance (ce) de MyCtrl sur le champ à utiliser dans le modèle via{{ MC.foo }}
OriginalL'auteur Sandro
Ramener ce comportement (personne ne sait pourquoi était-il changé?) vous pouvez ajouter:
à la fin de votre fonction de contrôleur (à condition que $champ d'application a été injecté à cette fonction de contrôleur).
Cela a un effet agréable d'avoir accès à la portée parent via le contrôleur de l'objet que vous pouvez obtenir de l'enfant avec
require: '^myParentDirective'
OriginalL'auteur Kamil Szot
$champ d'application est différent de 'cette', puis le contrôleur 'cette'.Ainsi, si vous mettez une console.journal(ce) à l'intérieur du contrôleur il vous donne un objet(contrôleur) et ce.addPane() ajoute addPane Méthode à l'Objet contrôleur. Mais le $champ d'application champ d'application différent et de méthode dans son champ d'application doivent être accessible par $champ d'application.methodName().
this.methodName()
à l'intérieur du contrôleur de moyens pour ajouter methos à l'intérieur de l'objet contrôleur.$scope.functionName()
est en HTML et à l'intérieur deCollez ce code dans votre éditeur de texte et ouvrez la console pour voir...
OriginalL'auteur Aniket Jha