Подтвердить что ты не робот

AngularJS - Зачем использовать "Controller as vm"?

В течение всего этого уик-энда я сильно переживал, не понимая, почему функция родительского контроллера не распознается дочерним контроллером.

Вскоре я понял, что причиной моего контроллера является vm:

 <div data-ng-controller="ParentCtrl as vm">
   <div data-ng-controller="Child1 as vm"></div>
   <div data-ng-controller="Child2 as vm"></div>
 </div>

Конечно, теперь все кажется очевидным, что ни child1, ни 2 не будут видеть функции в ParentCtrl, и если бы вместо этого я использовал предыдущий шаблон работы без vm, и вместо этого имел бы $scope, все было бы хорошо.

Итак, мой вопрос: "Что для кого-то выгодно использовать метод" vm ", и если он превосходит его не использовать, как можно вызвать вызовы функций в ParentCtrl, которые не испускают?

Спасибо

4b9b3361

Ответ 1

Одним из преимуществ использования контроллера как синтаксиса является то, что он позволяет вам определять ваши контроллеры как простую конструкторскую функцию javascript со свойствами и функциями, открытыми непосредственно из созданного объекта, а не в области $.

Например:

function MyController() {

    var ctl = this;

    ctl.message = 'You have not clicked anything yet.';

    ctl.onClick = function() {
        ctl.message = 'You clicked something.';
    };

    return ctl;
}

...

myModule.controller('MyController', MyController);

...

<div ng-controller="MyController as vm">
    <span>{{vm.message}}</span>
    <button ng-click="vm.onClick()">Click Me</button>
</div>

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

В конечном счете, это действительно зависит от предпочтения, но для меня мне действительно не нужно определять все непосредственно в области видимости и обрабатывать мои контроллеры как любой старый javascript-объект как можно больше.

Здесь отличная статья об использовании контроллера как: http://www.johnpapa.net/angularjss-controller-as-and-the-vm-variable/

Ответ 2

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

Ваш вопрос - это вопрос, о котором я некоторое время думал. Единственное реальное значение, которое я вижу, заключается в том, что когда вы используете вложенные контроллеры на странице, вы можете получить семантическую ссылку на каждую из областей, чтобы ваша разметка стала немного легче читать. Так, например:

<div ng-controller="CustomersCtrl as customers">
    <div ng-controller="OrdersCtrl as orders">
         <p>Showing{{customers.model.length}} customers with a total of {{orders.model.length}} orders</p>
    </div>
</div>

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

Ответ 3

То, что вы испытываете в этом примере, связано не только с использованием контроллера как синтаксиса; вместо этого это связано с тем, что ваши вложенные объекты скрывают родителя из-за именования.

Контроллер как опция очень полезен при интенсивной работе с другими языками, которые скомпилируются на JavaScript, например CoffeeScript или TypeScript. Он также позволяет создавать гораздо более легкие контроллеры, которые могут быть взаимозаменяемы с компонентами angular, из-за отсутствия необходимости в инъекции $scope. Это просто альтернативный синтаксис, но вы все равно можете использовать $scope, если хотите.

Настоящий вопрос заключается в том, почему люди, которые написали примеры контроллера в качестве синтаксиса, решили использовать "как vm". Технически синтаксис предназначен для обеспечения стиля кодирования в стиле MVVM, поэтому использование "как vm" может иметь смысл, но это раскрывает проблему, которую вы видите. Ваш родительский контроллер является объектом с именем vm, а ваш дочерний объект также имеет имя vm, поэтому дочерний объект скрывает родительский объект из представления. Если вместо этого вы назовете свои объекты по-разному, ваш дочерний объект не будет иметь проблемы с доступом к родительскому объекту, и на самом деле будет очень ясно, в коде, с которым объект, с которым вы работаете, исходит.

Ответ 4

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

У вас есть следующее:

<input ng-model="foo" />

Это может не работать должным образом. С другой стороны, если вы используете синтаксис SomeController as vm, вы автоматически закончите с этим:

<input ng-model="vm.foo" />

Это избавит вас от потенциальных проблем, когда привязка данных не работает должным образом.

Причины этого лежат в том, как прототипное наследование работает в JavaScript и описано здесь очень подробно: Каковы нюансы объема прототипа/прототипного наследования в AngularJS?

Ответ 5

Как я понимаю, основной причиной использования синтаксиса "контроллер как vm" является то, что контроллеры в angularjs действительно служат в качестве моделей (инкапсулируют данные и обеспечивают поведение) или модели представления (выставляют данные в html).

В большинстве случаев это сработало, но один основной недостаток, с которым я столкнулся, заключается в том, что трудно получить доступ к данным в родительском контроллере из дочернего контроллера и возможное решение (Получить родительский контроллер в дочернем контроллере, который все использует "контроллер как vm" нотация) не является элегантным.