expressions angularjs angularjs-scope this

expressions - ''this'' vs $ scope en los controladores AngularJS



angularjs expressions (7)

"¿Cómo funciona this y $scope en los controladores AngularJS?"

Respuesta corta :

  • this
    • Cuando se llama a la función de constructor del controlador, this es el controlador.
    • Cuando se llama a una función definida en un objeto $scope , this es el "alcance en efecto cuando se llamó a la función". Este puede (o no puede) ser el $scope que se define la función. Entonces, dentro de la función, this y $scope pueden no ser los mismos.
  • $scope
    • Cada controlador tiene un objeto $scope asociado.
    • Una función de controlador (constructor) es responsable de configurar las propiedades del modelo y las funciones / comportamiento en su $scope asociado.
    • Solo los métodos definidos en este objeto de $scope (y los objetos de alcance principal, si está en juego la herencia prototípica) son accesibles desde HTML / view. Por ejemplo, desde ng-click , filtros, etc.

Respuesta larga :

Una función de controlador es una función de constructor de JavaScript. Cuando la función del constructor se ejecuta (por ejemplo, cuando se carga una vista), this (es decir, el "contexto de la función") se establece en el objeto controlador. Así que en la función constructora del controlador de "pestañas", cuando se crea la función addPane

this.addPane = function(pane) { ... }

se crea en el objeto controlador, no en $ scope. Las vistas no pueden ver la función addPane, solo tienen acceso a las funciones definidas en $ scope. En otras palabras, en el HTML, esto no funcionará:

<a ng-click="addPane(newPane)">won''t work</a>

Después de que se ejecute la función constructora del controlador de "pestañas", tenemos lo siguiente:

La línea negra discontinua indica la herencia prototípica; un ámbito aislado se hereda prototípicamente de Scope . (No se hereda de forma prototípica del ámbito de aplicación en el que se encontró la directiva en el HTML).

Ahora, la función de enlace de la directiva de panel quiere comunicarse con la directiva de pestañas (lo que realmente significa que debe afectar a las pestañas aísla el alcance de $) de alguna manera. Se podrían usar eventos, pero otro mecanismo es hacer que la directiva del panel require el controlador de pestañas. (Parece que no hay ningún mecanismo para que la directiva del panel require las pestañas $ scope).

Entonces, esto plantea la pregunta: si solo tenemos acceso al controlador de pestañas, ¿cómo obtenemos acceso a las pestañas aísla $ scope (que es lo que realmente queremos)?

Bueno, la línea roja punteada es la respuesta. El "alcance" de la función addPane () (me refiero al alcance / cierre de la función de JavaScript aquí) le da a la función acceso a las pestañas aísla $ alcance. Es decir, addPane () tiene acceso a las "pestañas IsolateScope" en el diagrama anterior debido a un cierre que se creó cuando se definió addPane (). (Si en su lugar definimos addPane () en el objeto tabs $ scope, la directiva del panel no tendrá acceso a esta función y, por lo tanto, no tendría forma de comunicarse con las pestañas $ scope).

Para responder a la otra parte de su pregunta: how does $scope work in controllers? :

Dentro de las funciones definidas en $ scope, se establece en "el $ scope en efecto donde / cuando se llamó a la función". Supongamos que tenemos el siguiente HTML:

<div ng-controller="ParentCtrl"> <a ng-click="logThisAndScope()">log "this" and $scope</a> - parent scope <div ng-controller="ChildCtrl"> <a ng-click="logThisAndScope()">log "this" and $scope</a> - child scope </div> </div>

Y el ParentCtrl ( ParentCtrl ) tiene

$scope.logThisAndScope = function() { console.log(this, $scope) }

Al hacer clic en el primer enlace, se mostrará que this y $scope son iguales, ya que " el alcance en efecto cuando se llamó a la función " es el alcance asociado con ParentCtrl .

Al hacer clic en el segundo enlace se revelará this y $scope no son lo mismo, ya que " el alcance en efecto cuando se llamó a la función " es el alcance asociado con ChildCtrl . Así que aquí, this se establece en $scope ChildCtrl . Dentro del método, $scope sigue siendo $scope ParentCtrl .

Fiddle

Intento no usar this dentro de una función definida en $ scope, ya que se confunde qué $ scope está siendo afectado, especialmente considerando que ng-repeat, ng-include, ng-switch, y las directivas pueden crear sus propios ámbitos secundarios. .

En la sección "Crear componentes" de la página de inicio de AngularJS , hay un ejemplo:

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); } }

Observe cómo el método de select se agrega a $scope , pero el método addPane se agrega a this . Si lo cambio a $scope.addPane , el código se rompe.

La documentación dice que, de hecho, hay una diferencia, pero no menciona cuál es la diferencia:

Las versiones anteriores de Angular (pre 1.0 RC) le permitieron usar this intercambiable con el método $scope , pero este ya no es el caso. Dentro de los métodos definidos en el alcance, this y $scope son intercambiables (angular establece this en $scope ), pero no dentro del constructor de su controlador.

¿Cómo funciona this y $scope en los controladores AngularJS?


Las versiones anteriores de Angular (pre 1.0 RC) le permitieron usar esto de manera intercambiable con el método $ scope, pero este ya no es el caso. Dentro de los métodos definidos en el alcance, este y $ alcance son intercambiables (angular establece esto en $ alcance), pero no dentro del constructor de su controlador.

Para recuperar este comportamiento (¿alguien sabe por qué se cambió?) Puede agregar:

return angular.extend($scope, this);

al final de su función de controlador (siempre que se haya inyectado $ scope a esta función de controlador).

Esto tiene un buen efecto de tener acceso al ámbito principal a través del objeto controlador que puede obtener en child con require: ''^myParentDirective''


$ scope tiene un ''este'' diferente ''luego el controlador'' este ''. Por lo tanto, si coloca un console.log (este) dentro del controlador, le otorga un objeto (controlador) y this.addPane () agrega el método addPane al objeto controlador. Pero $ scope tiene un alcance diferente y todos los métodos en su alcance deben ser accedidos por $ scope.methodName (). this.methodName() dentro del controlador significa agregar methos dentro del objeto controlador. $scope.functionName() está en HTML y dentro

$scope.functionName(){ this.name="Name"; //or $scope.myname="myname"//are same}

Pega este código en tu editor y abre la consola para ver ...

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>this $sope vs controller</title> <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.7/angular.min.js"></script> <script> var app=angular.module("myApp",[]); app.controller("ctrlExample",function($scope){ console.log("ctrl ''this''",this); //this(object) of controller different then $scope $scope.firstName="Andy"; $scope.lastName="Bot"; this.nickName="ABot"; this.controllerMethod=function(){ console.log("controllerMethod ",this); } $scope.show=function(){ console.log("$scope ''this",this); //this of $scope $scope.message="Welcome User"; } }); </script> </head> <body ng-app="myApp" > <div ng-controller="ctrlExample"> Comming From $SCOPE :{{firstName}} <br><br> Comming from $SCOPE:{{lastName}} <br><br> Should Come From Controller:{{nickName}} <p> Blank nickName is because nickName is attached to ''this'' of controller. </p> <br><br> <button ng-click="controllerMethod()">Controller Method</button> <br><br> <button ng-click="show()">Show</button> <p>{{message}}</p> </div> </body> </html>


Acabo de leer una explicación bastante interesante sobre la diferencia entre los dos, y una creciente preferencia por adjuntar modelos al controlador y alias al controlador para vincular los modelos a la vista. http://toddmotto.com/digging-into-angulars-controller-as-syntax/ es el artículo. No lo menciona, pero al definir directivas, si necesita compartir algo entre varias directivas y no desea un servicio (hay casos legítimos en los que los servicios son una molestia), adjunte los datos al controlador de la directiva principal. El servicio $ scope ofrece muchas cosas útiles, siendo $ watch la más obvia, pero si todo lo que necesita es vincular los datos a la vista, usar el controlador plano y el ''controlador como'' en la plantilla está bien, y posiblemente sea preferible.


En este curso ( https://www.codeschool.com/courses/shaping-up-with-angular-js ) explican cómo usar "esto" y muchas otras cosas.

Si agrega el método al controlador a través de "este" método, debe llamarlo en la vista con el nombre del controlador "dot" su propiedad o método.

Por ejemplo, al usar su controlador en la vista, puede tener un código como este:

<div data-ng-controller="YourController as aliasOfYourController"> Your first pane is {{aliasOfYourController.panes[0]}} </div>


La razón por la que ''addPane'' se asigna a esto es debido a la directiva <pane> .

La directiva del pane require: ''^tabs'' , que coloca el objeto controlador de pestañas desde una directiva principal, en la función de enlace.

addPane se asigna a this para que la función de enlace del pane pueda verlo. Luego, en la función de enlace del pane , addPane es solo una propiedad del controlador de tabs , y es solo tabsControllerObject.addPane. Por lo tanto, la función de enlace de la directiva de panel puede acceder al objeto controlador de pestañas y, por lo tanto, acceder al método addPane.

Espero que mi explicación sea lo suficientemente clara ... es un poco difícil de explicar.


Te recomiendo que leas el siguiente post: AngularJS: "Controller as" o "$ scope"?

Describe muy bien las ventajas de usar "Controlador como" para exponer variables sobre "$ alcance".

Sé que usted preguntó específicamente sobre métodos y no variables, pero creo que es mejor atenerse a una técnica y ser coherente con ella.

En mi opinión, debido al problema de las variables discutido en la publicación, es mejor usar la técnica "Controlador como" y aplicarla a los métodos.