Dans la section "Créer des composants" de la page d'accueil d'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 la select
méthode est ajoutée $scope
, mais la addPane
méthode est ajoutée à this
. Si je le change en $scope.addPane
, le code se casse.
La documentation indique qu'il y a en fait une différence, mais elle ne mentionne pas la différence:
Les versions précédentes d'Angular (pré 1.0 RC) vous permettaient d'utiliser de
this
manière interchangeable avec la$scope
méthode, mais ce n'est plus le cas. À l'intérieur des méthodes définies sur la portéethis
et$scope
sont interchangeables (ensembles angulairesthis
à$scope
), mais pas autrement à l'intérieur du constructeur de votre contrôleur.
Comment fonctionne this
et $scope
fonctionne dans les contrôleurs AngularJS?
la source
Réponses:
Réponse courte :
this
this
est le contrôleur.$scope
objet est appelée,this
est la "portée en vigueur au moment de l'appel de la fonction". Il peut s'agir (ou non!) De la$scope
définition de la fonction. Donc, à l'intérieur de la fonction,this
et$scope
peut ne pas être le même.$scope
$scope
objet associé .$scope
.$scope
objet (et les objets de portée parent, si l'héritage prototypique est en jeu) sont accessibles à partir du HTML / de la vue. Par exemple, à partir deng-click
, filtres, etc.Réponse longue :
Une fonction de contrôleur est une fonction constructeur JavaScript. Lorsque la fonction constructeur s'exécute (par exemple, lorsqu'une vue se charge),
this
(c'est-à-dire que le "contexte de fonction") est défini sur l'objet contrôleur. Donc, dans la fonction constructeur du contrôleur "tabs", lorsque la fonction addPane est crééeil est créé sur l'objet contrôleur, pas sur $ scope. Les vues ne peuvent pas voir la fonction addPane - elles n'ont accès qu'aux fonctions définies sur $ scope. En d'autres termes, dans le HTML, cela ne fonctionnera pas:
Après l'exécution de la fonction de constructeur de contrôleur "tabs", nous avons ce qui suit:
La ligne noire en pointillés indique l'héritage prototypique - un oscilloscope isolé hérite de Scope de manière prototypique . (Il n'hérite pas de manière prototypique de la portée en vigueur où la directive a été rencontrée dans le HTML.)
Maintenant, la fonction de lien de la directive volet veut communiquer avec la directive tabs (ce qui signifie vraiment qu'elle doit affecter les onglets isoler $ scope d'une certaine manière). Les événements peuvent être utilisés, mais un autre mécanisme consiste à avoir la directive de volet
require
le contrôleur des onglets. (Il ne semble pas y avoir de mécanisme pour la directive de volet dansrequire
les onglets $ scope.)Donc, cela pose la question: si nous n'avons accès qu'au contrôleur d'onglets, comment pouvons-nous accéder aux onglets isoler $ scope (ce que nous voulons vraiment)?
Eh bien, la ligne pointillée rouge est la réponse. La "portée" de la fonction addPane () (je fais référence ici à la portée / fermetures de la fonction JavaScript) donne à la fonction l'accès aux onglets isolant $ scope. C'est-à-dire, addPane () a accès aux "onglets IsolateScope" dans le diagramme ci-dessus en raison d'une fermeture qui a été créée lorsque addPane () a été défini. (Si nous définissions plutôt addPane () sur l'objet tabs $ scope, la directive pane n'aurait pas accès à cette fonction, et par conséquent, elle n'aurait aucun moyen de communiquer avec les tabs $ scope.)
Pour répondre à l'autre partie de votre question
how does $scope work in controllers?
:Dans les fonctions définies sur $ scope,
this
est défini sur "le $ scope en vigueur où / quand la fonction a été appelée". Supposons que nous ayons le code HTML suivant:Et le
ParentCtrl
(uniquement) aCliquer sur le premier lien montrera que
this
et$scope
sont les mêmes, puisque " la portée en vigueur lorsque la fonction a été appelée " est la portée associée à laParentCtrl
.Cliquer sur le deuxième lien révélera
this
et ne$scope
sera pas le même, car " la portée en vigueur lorsque la fonction a été appelée " est la portée associée à laChildCtrl
. Donc , ici,this
est réglé surChildCtrl
« s$scope
. À l'intérieur de la méthode, se$scope
trouve toujours laParentCtrl
portée de $.Violon
J'essaie de ne pas utiliser à l'
this
intérieur d'une fonction définie sur $ scope, car cela devient déroutant quelle $ scope est affectée, d'autant plus que ng-repeat, ng-include, ng-switch et les directives peuvent tous créer leurs propres étendues enfants.la source
La raison pour laquelle «addPane» est attribué à cela est à cause de la
<pane>
directive.La
pane
directive faitrequire: '^tabs'
, qui place l'objet contrôleur tabs d'une directive parent, dans la fonction de lien.addPane
est affecté àthis
afin que lapane
fonction de liaison puisse le voir. Ensuite, dans lapane
fonction de lien,addPane
n'est qu'une propriété dutabs
contrôleur, et ce n'est que tabsControllerObject.addPane. Ainsi, la fonction de liaison de la directive pane peut accéder à l'objet contrôleur tabs et donc accéder à la méthode addPane.J'espère que mon explication est assez claire .. c'est un peu difficile à expliquer.
la source
Je viens de lire une explication assez intéressante sur la différence entre les deux, et une préférence croissante pour attacher des modèles au contrôleur et alias le contrôleur pour lier les modèles à la vue. http://toddmotto.com/digging-into-angulars-controller-as-syntax/ est l'article.
Il ne le mentionne pas mais lors de la définition des directives, si vous avez besoin de partager quelque chose entre plusieurs directives et que vous ne voulez pas de service (il y a des cas légitimes où les services sont un problème), attachez les données au contrôleur de la directive parent.
Le
$scope
service fournit de nombreuses choses utiles,$watch
étant les plus évidentes, mais si tout ce dont vous avez besoin pour lier des données à la vue, utiliser le contrôleur ordinaire et le `` contrôleur comme '' dans le modèle est correct et sans doute préférable.la source
Je vous recommande de lire le post suivant: AngularJS: "Controller as" ou "$ scope"?
Il décrit très bien les avantages d'utiliser "Controller as" pour exposer des variables sur "$ scope".
Je sais que vous avez posé des questions précises sur les méthodes et non sur les variables, mais je pense qu'il vaut mieux s'en tenir à une technique et y être cohérent.
Donc, à mon avis, en raison du problème des variables discuté dans le post, il est préférable d'utiliser simplement la technique "Controller as" et de l'appliquer également aux méthodes.
la source
Dans ce cours ( https://www.codeschool.com/courses/shaping-up-with-angular-js ), ils expliquent comment utiliser "ceci" et bien d'autres choses.
Si vous ajoutez une méthode au contrôleur via «cette» méthode, vous devez l'appeler dans la vue avec le nom du contrôleur «dot» votre propriété ou méthode.
Par exemple, en utilisant votre contrôleur dans la vue, vous pouvez avoir un code comme celui-ci:
la source
$scope
, alors merci de l'avoir mentionné.as
etthis
alors comment peut-il aider à expliquer la différence?$scope
n'a jamais été mentionné, j'ai appris à utiliser uniquementthis
dans les contrôleurs. Le problème est que lorsque vous commencez à gérer des promesses dans votre contrôleur, vous avez beaucoup de problèmes de référencesthis
et devez commencer à faire des choses commevar me = this
référencer le modèle àthis
partir de la fonction de retour de promesse. Donc à cause de cela, je suis toujours très confus quant à la méthode à utiliser,$scope
outhis
.var me = this
ou.bind(this)
chaque fois que vous ferez des promesses, ou d'autres choses lourdes de fermeture. Cela n'a rien à voir avec Angular.ng-controller="MyCtrl as MC"
équivaut à mettre$scope.MC = this
le contrôleur lui-même - il définit une instance (ceci) de MyCtrl sur la portée à utiliser dans le modèle via{{ MC.foo }}
Pour ramener ce comportement (quelqu'un sait-il pourquoi il a été changé?), Vous pouvez ajouter:
à la fin de votre fonction de contrôleur (à condition que $ scope ait été injecté dans cette fonction de contrôleur).
Cela a un bel effet d'avoir accès à la portée parent via un objet contrôleur que vous pouvez obtenir avec l'enfant
require: '^myParentDirective'
la source
$ scope a un `` ceci '' différent du contrôleur `` ceci '' .Ainsi, si vous mettez un console.log (ceci) dans le contrôleur, il vous donne un objet (contrôleur) et this.addPane () ajoute la méthode addPane à l'objet contrôleur. Mais la portée $ a une portée différente et toutes les méthodes de sa portée doivent être accédées par $ scope.methodName ().
this.methodName()
à l'intérieur du contrôleur signifie ajouter des méthos à l'intérieur de l'objet contrôleur.$scope.functionName()
est en HTML et à l'intérieurCollez ce code dans votre éditeur et ouvrez la console pour voir ...
la source