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, которые не испускают?
Спасибо
Ответы
Ответ 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" нотация) не является элегантным.