Sintaxis de "controlador como" de AngularJs: ¿aclaración?

121

Yo leí acerca de la nueva sintaxis de AngularJS respectocontroller as xxx

La sintaxis InvoiceController as invoicele dice a Angular que cree una instancia del controlador y lo guarde en la factura variable en el alcance actual.

Visualización:

ingrese la descripción de la imagen aquí

Ok, entonces no tendré el parámetro $scopeen mi controlador y el código será mucho más limpio en el controlador.

Pero

Tendré que especificar otro alias en la vista

Entonces hasta ahora podría hacer:

<input type="number" ng-model="qty"  />

....controller('InvoiceController', function($scope) {
   // do something with $scope.qty <--notice

Y ahora puedo hacer:

 <input type="number" ng-model="invoic.qty"  /> <-- notice 

  ....controller('InvoiceController', function() {
       // do something with  this.qty  <--notice

Pregunta

¿Cuál es el objetivo de hacerlo? eliminar de un lugar y agregar a otro lugar?

Estaré encantado de ver qué me estoy perdiendo.

Royi Namir
fuente
8
Este video lo explica muy bien. youtube.com/watch?v=tTihyXaz4Bo Creo que se usa para un código más limpio en el HTML.
Fizer Khan
1
Claridad. No me preocupa usar $ scope.x Vs. this.x en el controlador, pero en mi opinión, el enlace a {{invoice.x}} me dice más que solo {{x}} (en mi opinión). Además, me pregunto si esto resuelve un problema que escuché en angular donde los no objetos en el controlador tienen problemas (por lo que things.x estaría bien, pero x causaría un problema).
Matt Roberts
1
@MattRoberts para abordar su último comentario: el problema de no objeto al que hace referencia no es un problema angular, sino un hecho de la herencia prototípica de JavaScript. Hay una buena explicación de por qué sucede en angular aquí (junto con por qué lo controller asarregla).
Russ Matney el
¿Cómo reemplazaré $ scope. $ Broadcast? en este nuevo caso porque mi transmisión this. $ no parece funcionar
Gaurav
1
@Gaurav aún puede inyectar el servicio $ scope en su controlador, incluso si usa el controlador como sintaxis para algunas propiedades, métodos, etc.
Derek

Respuestas:

163

Hay varias cosas al respecto.

A algunas personas no les gusta la $scopesintaxis (no me pregunten por qué). Dicen que simplemente podrían usar this. Ese era uno de los objetivos.

Dejar en claro de dónde proviene una propiedad también es realmente útil.

Puede anidar controladores y al leer el html queda bastante claro de dónde proviene cada propiedad.

También puede evitar algunos de los problemas de la regla de puntos .

Por ejemplo, al tener dos controladores, ambos con el mismo nombre 'nombre', puede hacer esto:

<body ng-controller="ParentCtrl">
    <input ng-model="name" /> {{name}}

    <div ng-controller="ChildCtrl">
        <input ng-model="name" /> {{name}} - {{$parent.name}}
    </div>
</body>

Puede modificar tanto padre como hijo, no hay problema al respecto. Pero debe usar $parentpara ver el nombre del padre, porque lo sombreó en el controlador secundario. En código html masivo $parentpodría ser problemático, no sabes de dónde viene ese nombre.

Con controller asusted puede hacer:

<body ng-controller="ParentCtrl as parent">
    <input ng-model="parent.name" /> {{parent.name}}

    <div ng-controller="ChildCtrl as child">
      <input ng-model="child.name" /> {{child.name}} - {{parent.name}}
    </div>
</body>

El mismo ejemplo, pero es mucho más claro de leer.

Jesus Rodriguez
fuente
10
También aquí hay un buen ejemplo de por qué este enfoque puede ser confuso para algunos: stackoverflow.com/questions/25405543/…
Julian Hollmann
¡Esto es muy útil cuando anidas controladores!
C_J
1
Tengo problemas con una implementación similar de su respuesta, consulte stackoverflow.com/questions/38315538
Cody
Esto también le permite usar una clase es6 como su controlador y hacer referencia a los métodos en el HTML. foo() { ... }es más limpio que el camino $scope.foo = function() { ... }.
Brian McCutchon el
17

La principal ventaja con la controller assintaxis que veo es que puede trabajar con controladores como clases, no solo con algunas funciones de decodificación de $ scope, y aprovechar la herencia. A menudo me encuentro con una situación en la que hay una funcionalidad que es muy similar a una serie de controladores, y lo más obvio es crear una BaseControllerclase y heredarla.

A pesar de que existe una herencia $ alcance, que resuelve parcialmente este problema, algunas personas prefieren escribir código de una manera más orientada a objetos, lo que, en mi opinión, hace que el código sea más fácil de razonar y probar.

Aquí hay un violín para demostrar: http://jsfiddle.net/HB7LU/5796/

Roman Kolpak
fuente
1
Esto debería obtener más votos a favor, ya que el Fiddle es realmente útil
Mawg dice que reinstale a Monica
13

Creo que una ventaja particular es clara cuando tiene ámbitos anidados. Ahora quedará completamente claro exactamente de qué alcance proviene una referencia de propiedad.

David M. Karr
fuente
7

Fuente

Diferencia entre crear un controlador usando $scope objecty usar la “controller as”sintaxis y vm

Crear un controlador usando el objeto $ scope

Por lo general, creamos un controlador utilizando el objeto $ scope como se muestra en la lista a continuación:

myApp.controller("AddController", function ($scope) {



    $scope.number1;

    $scope.number2;

    $scope.result;

    $scope.add = function () {

        $scope.result = $scope.number1 + $scope.number2;

    }

});

Arriba estamos creando el AddController con tres variables y un comportamiento, usando el controlador y la vista de objeto $ scope, que se comunican entre sí. El objeto $ scope se usa para pasar datos y comportamiento a la vista. Pega la vista y el controlador juntos.

Esencialmente, el objeto $ scope realiza las siguientes tareas:

  1. Pase datos del controlador a la vista

  2. Pase el comportamiento del controlador a la vista

  3. Pega el controlador y visualiza juntos

  4. El objeto $ scope se modifica cuando cambia una vista y una vista se modifica cuando cambian las propiedades del objeto $ scope

Adjuntamos propiedades a un objeto $ scope para pasar datos y comportamiento a la vista. Antes de usar el objeto $ scope en el controlador, necesitamos pasarlo en la función del controlador como dependencias.

Uso de la sintaxis "controlador como" y vm

Podemos reescribir el controlador anterior usando el controlador como sintaxis y la variable vm como se muestra en la lista a continuación:

myApp.controller("AddVMController", function () {

    var vm = this;

    vm.number1 = undefined;

    vm.number2=undefined;

    vm.result =undefined;

    vm.add = function () {

        vm.result = vm.number1 + vm.number2;

    }

});

Esencialmente, estamos asignando esto a una variable vm y luego adjuntamos una propiedad y comportamiento a eso. En la vista podemos acceder al AddVmController usando el controlador como sintaxis. Esto se muestra en el listado a continuación:

<div ng-controller="AddVMController as vm">

            <input ng-model="vm.number1" type="number" />

            <input ng-model="vm.number2" type="number" />

            <button class="btn btn-default" ng-click="vm.add()">Add</button>

            <h3>{{vm.result}}</h3>

  </div>

Por supuesto, podemos usar otro nombre que "vm" en el controlador como sintaxis. Bajo el capó, AngularJS crea el objeto $ scope y adjunta las propiedades y el comportamiento. Sin embargo, al usar el controlador como sintaxis, el código es muy limpio en el controlador y solo el nombre del alias es visible en la vista.

Estos son algunos pasos para usar el controlador como sintaxis:

  1. Cree un controlador sin objeto $ scope.

  2. Asigne esto a una variable local. Preferí el nombre de la variable como vm, puede elegir el nombre que prefiera.

  3. Adjunte datos y comportamiento a la variable vm.

  4. En la vista, asigne un alias al controlador utilizando el controlador como sintaxis.

  5. Puede dar cualquier nombre al alias. Prefiero usar VM a menos que no esté trabajando con controladores anidados.

Al crear el controlador, no hay ventajas o desventajas directas de utilizar el enfoque de objeto $ scope o el controlador como sintaxis. Sin embargo, es puramente una elección, usar el controlador como sintaxis hace que el código JavaScript del controlador sea más legible y evita cualquier problema relacionado con este contexto.

Controladores anidados en el enfoque de objeto $ scope

Tenemos dos controladores como se muestra en el listado a continuación:

myApp.controller("ParentController", function ($scope) {



    $scope.name = "DJ";

    $scope.age = 32;

});

myApp.controller("ChildController", function ($scope) {



    $scope.age = 22;

    $scope.country = "India";



});

La propiedad "edad" está dentro de ambos controladores, y en la vista estos dos controladores se pueden anidar como se muestra en la siguiente lista:

<div ng-controller="ParentController">



            <h2>Name :{{name}} </h2>

            <h3>Age:{{age}}</h3>



             <div ng-controller="ChildController">

                    <h2>Parent Name :{{name}} </h2>

                    <h3>Parent Age:{{$parent.age}}</h3>

                    <h3>Child Age:{{age}}</h3>

                    <h3>Country:{{country}}</h3>

             </div>

        </div>

Como puede ver, para acceder a la propiedad de edad del controlador principal estamos usando $ parent.age. La separación del contexto no está muy clara aquí. Pero usando el controlador como sintaxis, podemos trabajar con controladores anidados de una manera más elegante. Digamos que tenemos controladores como se muestra en la lista a continuación:

myApp.controller("ParentVMController", function () {

    var vm = this;

    vm.name = "DJ";

    vm.age = 32;

});

myApp.controller("ChildVMController", function () {

    var vm = this;

    vm.age = 22;

    vm.country = "India";



});

En la vista, estos dos controladores se pueden anidar como se muestra en la lista a continuación:

<div ng-controller="ParentVMController as parent">



            <h2>Name :{{parent.name}} </h2>

            <h3>Age:{{parent.age}}</h3>



            <div ng-controller="ChildVMController as child">

                <h2>Parent Name :{{parent.name}} </h2>

                <h3>Parent Age:{{parent.age}}</h3>

                <h3>Child Age:{{child.age}}</h3>

                <h3>Country:{{child.country}}</h3>

            </div>

 </div>

En el controlador como sintaxis, tenemos un código más legible y se puede acceder a la propiedad principal utilizando el nombre de alias del controlador principal en lugar de utilizar la sintaxis $ parent.

Concluiré esta publicación diciendo que es puramente su elección si desea usar el controlador como sintaxis o el objeto $ scope. Tampoco hay una gran ventaja o desventaja, simplemente que el controlador como sintaxis que tiene control sobre el contexto es un poco más fácil de trabajar, dada la clara separación en los controladores anidados en la vista.

ShibinRagh
fuente
4

Creo que la principal ventaja es una API más intuitiva ya que los métodos / propiedades están asociados con la instancia del controlador directamente y no con el objeto de alcance. Básicamente, con el viejo enfoque, el controlador se convierte en una simple decoración para construir el objeto de alcance.

Aquí hay más información sobre esto: http://www.syntaxsuccess.com/viewarticle/551798f20c5f3f3c0ffcc9ff

TGH
fuente
3

Por lo que he leído, $ scope se eliminará en Angular 2.0, o al menos cómo vemos el uso de $ scope. Puede ser bueno comenzar a usar el controlador a medida que se acerca el lanzamiento de 2.0.

Enlace de video aquí para más discusión al respecto.

jason328
fuente