AngularJs синтаксис «контроллер как» - пояснение?

121

Я читал о новом синтаксисе от angularJS относительноcontroller as xxx

Синтаксис InvoiceController as invoiceсообщает Angular создать экземпляр контроллера и сохранить его в переменной invoice в текущей области.

Визуализация:

введите описание изображения здесь

Хорошо, у меня не будет параметра $scopeв моем контроллере, и код в контроллере будет намного чище.

Но

Мне нужно будет указать другой псевдоним в представлении

Итак, до сих пор я мог:

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

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

И теперь я могу:

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

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

Вопрос

Какова цель этого? убрать из одного места и добавить в другое?

Буду рад увидеть, что мне не хватает.

Ройи Намир
источник
8
Это видео очень хорошо объясняет. youtube.com/watch?v=tTihyXaz4Bo Я думаю, он используется для более чистого кода в HTML.
Fizer Khan
1
Ясность. Меня не беспокоит использование $ scope.x против this.x в контроллере, но, на мой взгляд, привязка к {{invoice.x}} говорит мне больше, чем просто {{x}} (imho). Кроме того, мне интересно, решает ли это проблему, о которой я слышал в angular, когда не-объекты в контроллере имеют проблемы (так что things.x будет хорошо, но x вызовет проблему).
Мэтт Робертс
1
@MattRoberts, чтобы обратиться к вашему последнему комментарию - проблема, не связанная с объектами, на которую вы ссылаетесь, не является угловой проблемой, а скорее фактом прототипного наследования javascript. Там хорошее объяснение того , почему это происходит в угловой здесь (наряду с тем, почему controller asфиксирует его).
Расс Матни
Как мне заменить $ scope. $ Broadcast? в этом новом случае, потому что моя трансляция this. $, похоже, не работает
Гаурав,
1
@Gaurav, вы все равно можете внедрить службу $ scope в свой контроллер, даже если вы используете контроллер как синтаксис для некоторых свойств, методов и т. Д.
Дерек

Ответы:

163

В этом есть несколько моментов.

Некоторым людям не нравится $scopeсинтаксис (не спрашивайте меня, почему). Говорят, что можно было просто использовать this. Это была одна из целей.

Очень полезно также прояснить, откуда берется свойство.

Вы можете вкладывать контроллеры, и при чтении html довольно ясно, где находится каждое свойство.

Вы также можете избежать некоторых проблем с правилом точки .

Например, имея два контроллера, оба с тем же именем name, вы можете сделать это:

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

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

Вы можете изменить как родительский, так и дочерний, без проблем. Но вам нужно использовать, $parentчтобы увидеть имя родителя, потому что вы затеняли его в своем дочернем контроллере. В массивном html-коде $parentмогут возникнуть проблемы, вы не знаете, откуда взялось это имя.

С ним controller asможно:

<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>

Тот же пример, но его гораздо легче читать.

Хесус Родригес
источник
10
Также вот довольно хороший пример того, почему этот подход может сбивать с толку некоторых: stackoverflow.com/questions/25405543/…
Джулиан Холлманн,
Это очень полезно при встраивании контроллеров!
C_J
1
У меня проблемы с аналогичной реализацией вашего ответа, см. Stackoverflow.com/questions/38315538
Коди
Это также позволяет вам использовать класс es6 в качестве контроллера и ссылаться на методы в HTML. foo() { ... }намного чище, чем $scope.foo = function() { ... }.
Брайан МакКатчон,
17

Основное преимущество controller asсинтаксиса, которое я вижу, заключается в том, что вы можете работать с контроллерами как с классами, а не только с некоторыми функциями, украшающими область видимости, и пользоваться преимуществами наследования. Я часто сталкиваюсь с ситуацией, когда есть функциональность, которая очень похожа на ряд контроллеров, и наиболее очевидным является создание BaseControllerкласса и наследование от него.

Несмотря на то, что существует наследование $ scope, которое частично решает эту проблему, некоторые люди предпочитают писать код в более ООП манере, что, на мой взгляд, упрощает анализ и тестирование кода.

Вот скрипка для демонстрации: http://jsfiddle.net/HB7LU/5796/

Роман Колпак
источник
1
Это должно получить больше голосов, так как Fiddle действительно полезен
Mawg говорит восстановить Монику
13

Я считаю, что одно конкретное преимущество очевидно, когда у вас есть вложенные области видимости. Теперь будет совершенно ясно, из какой области исходит ссылка на свойство.

Дэвид М. Карр
источник
7

Источник

Разница между созданием контроллера с использованием $scope objectи использованием “controller as”синтаксиса и vm

Создание контроллера с использованием объекта $ scope

Обычно мы создаем контроллер, используя объект $ scope, как показано в листинге ниже:

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



    $scope.number1;

    $scope.number2;

    $scope.result;

    $scope.add = function () {

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

    }

});

Выше мы создаем AddController с тремя переменными и одним поведением, используя контроллер объекта $ scope и представление, которые взаимодействуют друг с другом. Объект $ scope используется для передачи данных и поведения представлению. Он склеивает представление и контроллер вместе.

По сути, объект $ scope выполняет следующие задачи:

  1. Передача данных из контроллера в представление

  2. Передача поведения из контроллера в представление

  3. Склеивает контроллер и вид вместе

  4. Объект $ scope изменяется при изменении представления, а представление изменяется при изменении свойств объекта $ scope.

Мы прикрепляем свойства к объекту $ scope, чтобы передавать данные и поведение в представление. Прежде чем использовать объект $ scope в контроллере, нам нужно передать его функции контроллера в качестве зависимостей.

Использование синтаксиса «контроллер как» и vm

Мы можем переписать указанный выше контроллер, используя контроллер в качестве синтаксиса и переменную vm, как показано в листинге ниже:

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;

    }

});

По сути, мы назначаем это переменной vm, а затем присоединяем к ней свойство и поведение. В представлении мы можем получить доступ к AddVmController, используя контроллер в качестве синтаксиса. Это показано в листинге ниже:

<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>

Конечно, мы можем использовать в контроллере в качестве синтаксиса другое имя, кроме «vm». Под капотом AngularJS создает объект $ scope и прикрепляет свойства и поведение. Однако при использовании контроллера в качестве синтаксиса код контроллера становится очень чистым, и в представлении отображается только псевдоним.

Вот несколько шагов по использованию контроллера в качестве синтаксиса:

  1. Создайте контроллер без объекта $ scope.

  2. Назначьте это локальной переменной. Я предпочел имя переменной как vm, вы можете выбрать любое имя по вашему выбору.

  3. Присоедините данные и поведение к переменной vm.

  4. В представлении дайте контроллеру псевдоним, используя контроллер в качестве синтаксиса.

  5. Вы можете дать псевдониму любое имя. Я предпочитаю использовать vm, если я не работаю с вложенными контроллерами.

При создании контроллера нет прямых преимуществ или недостатков использования подхода $ scope object или контроллера в качестве синтаксиса. Однако это чисто вопрос выбора, однако использование контроллера в качестве синтаксиса делает код JavaScript контроллера более читабельным и предотвращает любые проблемы, связанные с этим контекстом.

Вложенные контроллеры в объектном подходе $ scope

У нас есть два контроллера, как показано в листинге ниже:

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



    $scope.name = "DJ";

    $scope.age = 32;

});

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



    $scope.age = 22;

    $scope.country = "India";



});

Свойство age находится внутри обоих контроллеров, и в представлении эти два контроллера могут быть вложены, как показано в листинге ниже:

<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>

Как видите, для доступа к свойству age родительского контроллера мы используем $ parent.age. Разделение контекста здесь не очень четкое. Но используя контроллер в качестве синтаксиса, мы можем работать с вложенными контроллерами более элегантно. Допустим, у нас есть контроллеры, как показано в листинге ниже:

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";



});

На представлении эти два контроллера могут быть вложены, как показано в листинге ниже:

<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>

В контроллере как синтаксис у нас есть более читаемый код, и к родительскому свойству можно получить доступ, используя псевдоним родительского контроллера вместо использования синтаксиса $ parent.

Я завершу этот пост, сказав, что это исключительно ваш выбор, хотите ли вы использовать контроллер как синтаксис или объект $ scope. У них нет огромных преимуществ или недостатков, просто контроллер как синтаксис, который вы контролируете в контексте, немного проще в работе, учитывая четкое разделение вложенных контроллеров в представлении.

ShibinRagh
источник
4

Я считаю, что основным преимуществом является более интуитивно понятный API, поскольку методы / свойства связаны напрямую с экземпляром контроллера, а не с объектом области. По сути, при старом подходе контроллер становится просто украшением для создания объекта области.

Вот еще немного информации по этому поводу : http://www.syntaxsuccess.com/viewarticle/551798f20c5f3f3c0ffcc9ff

TGH
источник
3

Из того, что я прочитал, $ scope будет удален в Angular 2.0, или, по крайней мере, как мы рассматриваем использование $ scope. Было бы неплохо начать использовать контроллер по мере приближения выпуска 2.0.

Ссылка на видео здесь для более подробного обсуждения этого.

jason328
источник