Предпочтительный способ объявления контроллеров

Существует несколько доступных способов определения контроллера в AngularJs. Конкретно:

  1. синтаксис "прикрепить к $scope"
  2. синтаксис "контроллер как"
  3. controller() функция

Демонстрация кода из вышеперечисленного:

// 1)
ng-controller="MyControllerFn"

// 2)
ng-controller="MyControllerFn as myCtrl"

// 3)
myModule.controller("myCtrl", MyControllerFn);
// or
myApp.controller("myCtrl", ["$scope", function($scope) {

}]);

Конечно, у каждого из них есть свои плюсы и минусы. В настоящее время я использую вариант 1). Моя проблема в том, что я не знаю, не упущу ли я что-нибудь в долгосрочной перспективе, теперь, когда мне доступен новый синтаксис «контроллер как». Наш проект довольно большой, и я не могу представить, что буду переписывать все на новый синтаксис через год или около того только потому, что старый устарел. Я бы предпочел постепенно переходить сейчас и писать новый код «хорошим способом», начиная с сегодняшнего дня.

Немного ЗА и ПРОТИВ:

1)

  • (хорошо) меньше шаблонов по сравнению с 3), так как автоматическое обнаружение контроллеров позаботится об объявлении для вас, когда оно встречает директиву ng-controller
  • (плохо) поддерживает правильный DI: MyControllerFn.$inject = [...]
  • (плохо) сложнее ориентироваться в дереве наследования контроллера

2)

  • (хороший) псевдоним контроллера дает понять, к каким переменным области относятся
  • (хороший) более чистый синтаксис контроллера из-за назначения переменных this
  • (хорошо), кажется, улучшается поддержка инструментов (IDE)
  • (плохо) склонен к ошибке добавления слишком большого количества элементов в область видимости, например: `this.arr = ...; // массив из 1 млн элементов'

3)

  • (нейтрально) минификация сделана правильно (ну, это можно сделать с помощью свойства $inject)
  • (плохо) более подробный синтаксис, которого можно полностью избежать с помощью автообнаружения

Хорошо, так я что-то пропустил? Может быть, я не вижу чего-то очевидного, так как совсем недавно перешел на 1.2?


= РЕДАКТИРОВАТЬ

Чтобы было понятно, есть разница между привязкой и объявлением контроллера. Первые два продемонстрированных варианта связаны с привязкой контроллера к DOM, а третий — с явным объявлением его в модуле angular. Противоположностью последнему было бы разрешение Angular проходить через DOM и автоматически обнаруживать контроллер, что я предпочитаю делать.


person ŁukaszBachman    schedule 28.05.2014    source источник


Ответы (1)


Чтобы все было ясно:

Прежде всего, необходимо выполнить две отдельные вещи:

  1. Определите реализацию контроллера (т.е. функцию, которая будет "newed" для создания экземпляра контроллера).
  2. Привяжите контроллер к элементу DOM (например, «эта часть представления управляется экземпляром контроллера, известным как 'someCtrl'»).

Затем работа Angular заключается в том, чтобы связать вещи вместе:

  1. Я вижу элемент в представлении.
  2. Я вижу, что элемент x привязан к контроллеру y.
  3. Я нахожу функцию, которая зарегистрирована как реализация контроллера с именем y.
  4. Я создаю новый экземпляр контроллера, используя эту функцию.
  5. Я передаю новый экземпляр контроллера элементу (т.е. оцениваю каждое выражение Angular, найденное в элементе и его потомках, по отношению к этому экземпляру контроллера, если только поддерево представления не привязано к другому экземпляру контроллера и т. д.).

(1) и (2) — это способы привязки контроллера к элементу DOM.
Вдобавок к ним есть также свойство controller директивы и свойство controller директивы ngRoute, о которых вы вообще не упоминаете.

(3) — это способ регистрации реализации контроллера с помощью DI Angular (который заботится о создании экземпляра контроллера, привязанного к определенному элементу.
В этом смысле автоматическое сопоставление реализации контроллера по имени функции (то, что вы ссылаться как (автообнаружение) является альтернативой (3), так что давайте назовем его (4).

Согласно вышеизложенному, (1) и (2) не являются альтернативными подходами к (3) и (4), но оба они необходимы и дополняют друг друга.


Из вышеперечисленных функций «автообнаружение» — это та, на которую я хотел бы полагаться меньше всего.
Она кажется хакерской/не очень «надежной», и ее цель — сократить объем необходимого кода для быстрого создания небольших прототипов или примеров, не использовать в крупномасштабных производственных приложениях.

Из Руководства для разработчиков Angular:

ПРИМЕЧАНИЕ. Хотя Angular позволяет создавать функции контроллера в глобальной области видимости, делать это не рекомендуется. В реальном приложении вы должны использовать метод .controller вашего модуля Angular [...]


ИМО, настоящая дискуссия идет о controller против contoller as.

Вот некоторые соображения:

  1. Функция controller as была новой функцией и, возможно, все еще находилась на стадии оценки. Вероятно, он здесь, чтобы остаться, но я бы не стал ставить на это все свои деньги.

  2. В синтаксисе controller as нет фактического $scope (то есть объекта Scope, потомка $rootScope и т. д.). Этот факт имеет некоторые последствия в отношении того, как вы выполняете некоторые вещи, специфичные для $scope, например. регистрация слушателей с $on(), $watching над свойствами и т. д.

  3. Синтаксис controller as может улучшить ремонтопригодность/читабельность представлений, поскольку он явно указывает, к какому контроллеру относится каждое свойство, — он позволяет избежать случаев, когда свойство доступно через прототипное наследование, перезаписывается и т. д. С другой стороны, отсутствие прототипного наследования создает ограничения на то, как данные могут распространяться.


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

person gkalpak    schedule 28.05.2014
comment
Что ж, придется немного поспорить :-) Я понимаю концепцию declaration и definition в языках программирования, в Angular тоже. Я знаю, что 1 и 2 - это методы, используемые для привязки, но мой вопрос был о выборе одного над другим. 3 и 4, согласен, они дополняют друг друга, но определенно NOT NEEDED из-за автоматического сопоставления. Для меня менее надежным является именно 3 и 4, потому что мне нужен дополнительный код, чтобы заставить его работать (нарушение соглашения о конфигурации). Что касается последнего вопроса - вы уверены, что this на самом деле не является $scope при использовании синтаксиса controller as? - person ŁukaszBachman; 29.05.2014
comment
1) Ваш вопрос выглядел так, как будто вы считаете (3) альтернативным подходом к (1) и (2) (что явно не так, это совершенно другое). Как (4) я имею в виду автообнаружение (не ваш 3b). Либо (3), либо (4) абсолютно необходимо ((4) это ваше автообнаружение, поэтому вам нужно либо полагаться на автообнаружение (4), либо явно регистрировать контроллеры (3) - но одно из двух абсолютно необходимо). Дополнительный код не означает менее надежный (и дополнительный код в одну строку не так уж и много накладных расходов). - person gkalpak; 29.05.2014
comment
Рассматривали ли вы последствия того, что сторонняя библиотека определяет функцию с тем же именем, что и ваш контроллер, в глобальной области? Автоматическое обнаружение более подвержено ошибкам (и, следовательно, менее надежно). И, наконец, да, я совершенно уверен, что this не $scope. - person gkalpak; 29.05.2014
comment
Извините за длинные комментарии, но было много тем для обсуждения :) Как я уже сказал, я считаю, что автоматическое обнаружение не готово к производству, но это личное мнение, и другие могут думать иначе ( Я буду искать более веские доказательства, подтверждающие мое мнение, и обновлю, если что-нибудь найду). Для меня настоящая дилемма controller против controller as. Я упомянул существующие различия (и мои соображения) - как я уже сказал, у меня нет сильных чувств ни к одному из них (но я использую первое и немного одобряю его). - person gkalpak; 29.05.2014
comment
Да, я понял, что мой список из 1..3 мог быть воспринят как альтернатива, что не входило в мои намерения. Исправим это. Конфликты имен очень маловероятны, и я бы не стал жертвовать удобочитаемостью и простотой обслуживания моего кода из-за боязни столкнуться с проблемами. Я очень люблю автодискавери и до сих пор не могу найти ничего против :) - person ŁukaszBachman; 29.05.2014
comment
Вы понимаете, что нечитаемость и несопровождаемость, на которые вы ссылаетесь, не более чем на половину длины: .controller('someCtrlName', someCtrlFunc); (не говоря уже о том, что так гораздо удобнее поддерживать по мере роста вашего приложения). - person gkalpak; 29.05.2014
comment
Кстати, я обновил свой ответ цитатой из Руководства разработчика Angular, в котором говорится об автоматическом обнаружении... - person gkalpak; 29.05.2014
comment
@ŁukaszBachman: Вы смотрели обновленный ответ? Все еще не убеждены? :) - person gkalpak; 05.06.2014
comment
Мне еще предстоит кое-что оценить :) Эта заметка от команды AngularJs меня не убеждает, см. это: groups.google.com/forum/#!topic/angular/UF8Np3B0Lr4 Я согласен с утверждением, что возможное загрязнение пространства имен является слишком расплывчатой ​​причиной. - person ŁukaszBachman; 05.06.2014
comment
Я прочитал эту ветку и мне интересно, как у вас сложилось впечатление, что загрязнение глобального пространства имен не является проблемой. Кажется, все согласны с этим (кроме одного парня). Итак, один случайный парень знает лучше, чем: множество случайных парней, несколько не очень случайных парней (в этом треде есть несколько легенд Angular) и сама команда Angular! Вау, ты, должно быть, чертовски уверенный в себе парень :) В любом случае, я все делаю то, что тебе говорят (несмотря на то, что все остальные говорят тебе обратное) - это часто требует некоторого обучения на собственном опыте, но это весело! - person gkalpak; 05.06.2014
comment
Но загрязнять глобальное пространство имен не рекомендуется. не рекомендуется не означает, что это ошибка, не означает, что завтра ваше приложение сломается, не означает, что котенок умрет. Это просто означает, что это может (или не может) сделать ваше приложение менее удобным в сопровождении, менее расширяемым и более полезным для вас в будущем (или других). Но, в конце концов, решать вам :) - person gkalpak; 05.06.2014