En la sección "Crear componentes" de la página de inicio de AngularJS , hay este 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 select
se agrega el método $scope
, pero addPane
se agrega el método 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
indistintamente con el$scope
método, pero este ya no es el caso. Dentro de los métodos definidos en el alcancethis
y$scope
son intercambiables (conjuntos angularesthis
a$scope
), pero no de otra manera dentro del constructor de su controlador.
¿Cómo funciona this
y $scope
funciona en los controladores AngularJS?
angularjs
angularjs-scope
this
Alexei Boronine
fuente
fuente
Respuestas:
Respuesta corta :
this
this
es el controlador.$scope
se llama a una función definida en un objeto,this
es el "alcance vigente cuando se llamó a la función". Esto puede (¡o no!) Ser en el$scope
que se define la función. Entonces, dentro de la función,this
y$scope
puede no ser lo mismo.$scope
$scope
objeto asociado .$scope
.$scope
objeto (y los objetos del ámbito principal, si la herencia prototípica está en juego) son accesibles desde la vista / HTML. Por ejemplo, desdeng-click
, filtros, etc.Respuesta larga :
Una función de controlador es una función constructora de JavaScript. Cuando se ejecuta la función del constructor (por ejemplo, cuando se carga una vista),
this
(es decir, el "contexto de la función") se establece en el objeto controlador. Entonces, en la función del constructor del controlador "pestañas", cuando se crea la función addPanese 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á:
Después de que se ejecuta la función del constructor del controlador "pestañas", tenemos lo siguiente:
La línea negra discontinua indica herencia prototípica: un alcance aislado hereda prototípicamente de Scope . (No hereda prototípicamente del alcance en efecto donde 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 aislar $ scope de alguna manera). Se podrían usar eventos, pero otro mecanismo es hacer que el panel dirija
require
el controlador de pestañas. (Parece que no hay ningún mecanismo para la directiva de panel pararequire
las pestañas $ scope).Entonces, esto plantea la pregunta: si solo tenemos acceso al controlador de pestañas, ¿cómo podemos acceder a las pestañas aislar $ scope (que es lo que realmente queremos)?
Bueno, la línea punteada roja es la respuesta. El "alcance" de la función addPane () (me refiero al alcance / cierres de la función de JavaScript aquí) le da a la función acceso a las pestañas aislar $ scope. 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 de pestañas $ scope, la directiva de panel no tendría acceso a esta función y, por lo tanto, no tendría forma de comunicarse con las pestañas $ scope).
Para responder la otra parte de su pregunta
how does $scope work in controllers?
:Dentro de las funciones definidas en $ scope,
this
se establece en "el alcance de $ vigente donde / cuando se llamó a la función". Supongamos que tenemos el siguiente HTML:Y el
ParentCtrl
(Solamente) tieneAl hacer clic en el primer enlace se mostrará eso
this
y$scope
son lo mismo, ya que " el alcance en vigor cuando se llamó a la función " es el alcance asociado con elParentCtrl
.Al hacer clic en el segundo enlace se revelará
this
y no$scope
es lo mismo, ya que " el alcance en vigor cuando se llamó a la función " es el alcance asociado con elChildCtrl
. Así que aquí,this
se establece enChildCtrl
's$scope
. Dentro del método,$scope
sigue siendo elParentCtrl
alcance de $.Violín
Intento no usar
this
dentro de una función definida en $ scope, ya que se vuelve confuso qué $ scope está siendo afectado, especialmente teniendo en cuenta que ng-repeat, ng-include, ng-switch y directivas pueden crear sus propios ámbitos secundarios.fuente
La razón por la que 'addPane' se asigna a esto se debe a la
<pane>
directiva.La
pane
directiva sírequire: '^tabs'
, que coloca el objeto controlador de pestañas de una directiva principal, en la función de enlace.addPane
está asignado parathis
que lapane
función de enlace pueda verlo. Luego, en lapane
función de enlace,addPane
es solo una propiedad deltabs
controlador, 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.
fuente
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 cuando define 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
$scope
servicio proporciona muchas cosas útiles,$watch
siendo lo más obvio, pero si todo lo que necesita para vincular datos a la vista, usar el controlador simple y 'controlador como' en la plantilla está bien y posiblemente sea preferible.fuente
Le recomiendo que lea la siguiente publicación: AngularJS: "Controller as" o "$ scope"?
Describe muy bien las ventajas de usar "Controlador como" para exponer variables sobre "$ scope".
Sé que preguntaste específicamente sobre métodos y no sobre variables, pero creo que es mejor seguir una técnica y ser coherente con ella.
Entonces, en mi opinión, debido al problema de variables discutido en la publicación, es mejor usar la técnica "Controlador como" y también aplicarla a los métodos.
fuente
En este curso ( https://www.codeschool.com/courses/shaping-up-with-angular-js ) explican cómo usar "esto" y muchas otras cosas.
Si agrega un método al controlador a través de "este" método, debe llamarlo en la vista con el nombre del controlador "dot" de su propiedad o método.
Por ejemplo, al usar su controlador en la vista, puede tener un código como este:
fuente
$scope
, así que gracias por mencionarlo.as
y,this
entonces, ¿cómo puede ayudar a explicar la diferencia?$scope
nunca se mencionó, aprendí a usar solothis
en los controladores. El problema es que cuando comienza a tener que manejar promesas en su controlador, tiene un problema de muchas referenciasthis
y tiene que comenzar a hacer cosas comovar me = this
hacer referencia al modelothis
desde dentro de la función de devolución de promesa. Por eso, todavía estoy muy confundido acerca de qué método debería usar,$scope
othis
.var me = this
o.bind(this)
cuando haga Promesas u otras cosas pesadas para el cierre. No tiene nada que ver con Angular.ng-controller="MyCtrl as MC"
es equivalente a poner$scope.MC = this
en el propio controlador - que define una instancia (esto) de MyCtrl sobre el alcance para su uso en la plantilla a través de{{ MC.foo }}
Para recuperar este comportamiento (¿alguien sabe por qué se cambió?) Puede agregar:
al final de su función de controlador (siempre que se inyectó $ scope a esta función de controlador).
Esto tiene un buen efecto de tener acceso al ámbito primario a través del objeto controlador que puede obtener en el niño con
require: '^myParentDirective'
fuente
$ scope tiene un 'this' diferente que el controlador 'this'. Por lo tanto, si coloca un console.log (this) dentro del controlador, le da un objeto (controller) y this.addPane () agrega el método addPane al Object del controlador. Pero $ scope tiene un alcance diferente y todos los métodos en su alcance deben ser accedidos por $ scope.methodName ().
this.methodName()
Controlador interno significa agregar metos dentro del objeto controlador.$scope.functionName()
está en HTML y dentroPegue este código en su editor y abra la consola para ver ...
fuente