Развлекаемся с миксинами в Angular

Развлекаемся с миксинами в Angular

От автора: в своем последнем посте я писал об Управлении состоянием в Angular. В конце я написал о Connect Mixin, который я использовал в то время. Ладно, если честно, я имел в виду компонент более высокого уровня, но в Angular это не так просто сделать. Итак, давайте по порядку. Сегодня говорим о том, как использовать в Angular.js миксины.

Цель Connect Mixin — подключиться к хранилищу NGRX и предоставить нам из него данные. Если вы не хотите читать весь пост, я бы посоветовал вам перейти к части Connect-Mixin. Или, по крайней мере, прочитайте последнюю часть: Плохие миксины.

1. Что такое миксины?

В программировании MixIn — это стиль разработки программного обеспечения, в котором функциональные единицы создаются в классе, а затем смешиваются с другими классами.

Класс mixin — это родительский класс, унаследованный от другого — но не как средство специализации. Как правило, миксин экспортирует сервисы в дочерний класс, но семантика не подразумевает, что дочерний класс «является своего рода» родителем.

По моему собственному определению: Миксин — это особый тип наследования классов. Они дают вам возможность множественного наследования и позволяют использовать код из разных классов. Но для чего это нужно?

2. Для чего используются миксины

Они позволяют нам распределить кросс-функциональное поведение. Скажем, у нас есть некоторые общие функции для подключения к хранилищу redux и некоторые общие функции, которые мы хотим совместно использовать для многих представлений. Примитивный подход может выглядеть следующим образом:

Множественное наследование через расширение не допускается

Но компилятор не совсем доволен этим. Выдается ошибка: Classes can only extend a single class!

Как мы можем решить эту проблему? Миксин нам в помощь. Давайте сразу рассмотрим код. Чтобы достичь желаемого поведения, мы должны создать некоторые функции, которые смешивают (MixIn ^^) поведение. Такая функция Mixin ожидает по крайней мере один аргумент, а именно класс, который мы хотим расширить. И это именно то, что происходит внутри функции. Она возвращает выражение класса, которое выходит из данного класса и добавляет к нему дополнительное поведение:

Образец миксинов

Теперь мы можем улучшить базовый класс CommitView с помощью поведения Connect-Mixin и поведения View-Mixin. По сути, функция Mixin берет определение класса и дополняет его. В моем примере выше View-Mixin добавляет поле viewMode, а Connect-Mixin подключается к конкретной реализации хранилища. Чтобы увидеть полную реализацию Connect-Mixin, пожалуйста, прокрутите вниз до пункта 4.

3. Миксины в Angular Material

Просматривая определенный источник Angular Material, я заметил, что там тоже используются миксины Это было своего рода сюрпризом, но в этом есть смысл. В Material есть много общих функций в разных директивах, таких как Color Mixin, Disabled Mixin, Tabindex Mixin, Error Sate Mixin или Initialized Mixin. Создание нескольких базовых классов со всеми различными вариантами поведения было бы просто слишком затратно и с трудом обслуживаемо. Я думаю, что это прекрасный пример правильного использования миксинов. Посмотрите на Color Mixin:

До введения миксинов в Angular Material один и тот же код копировался снова и снова, вставлялся в несколько компонентов.

4. Connect Mixin

Как и было обещано выше, вот Connect Mixin. Его задача — работать аналогично компоненту высшего порядка Connect из React Redux. Это позволяет вам указать селекторы и действия, которые затем смешиваются с данным компонентом.
В этом мини-примере я создал и подключил Counter Counter к хранилищу NGRX.

Примитивный счетчик — я знаю

Давайте посмотрим на использование Connect Mixin. Обратите внимание, что это очень тонкая реализация компонента контейнера. Контейнер выполняет только одну задачу: подключение счетчика. Это другой, но чистый подход к компонентам контейнера. Чем он отличается? В Angular Applications я часто вижу очень большие компоненты контейнеров, которые соединяют все виды данных из хранилища и выполняют дополнительную бизнес-логику. Они таким образом не соответствуют принципу единичной ответственности.

Чтобы использовать включение зависимостей Angular, мы должны добавить между ними класс CounterViewBase и расширить контейнер из созданного класса Mixins. Классы Mixin должны иметь конструктор с единственным параметром типа any[], и поэтому мы не можем внедрить Injector непосредственно в Mixin.

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

Шаблон контейнера счетчика

Сам Connect-Mixin ожидает компонент, который содержит инжектор, поэтому мы создали интерфейс HasInjector. Нам нужен инжектор, чтобы получить во время выполнения сервис NGRX Store. Мы могли бы включить NGRX Store непосредственно в контейнер, но я хотел отделить контейнер от реализации хранилища, которую мы используем.

Хотя в этом примере я не использую объект vm в компоненте контейнера, типы Inputs <I> и Outputs <O> дают нам безопасную обработку типов.

5. Миксины плохие?

Я должен признать, что до написания этого исследования я был скорее критически настроен к наследованию. Я пытался избегать наследования, особенно множественного, любой ценой. Но мир не состоит только из черного и белого. И для библиотек компонентов, таких как Angular Material, использование множественного наследования через миксины имеет смысл.

Я бы не стал злоупотреблять этим. Если вам нужно гораздо более динамичное поведение в компонентах, я бы стремился к «Составлению вместо наследования». Составление допускает взаимозаменяемое поведение во время выполнения и придерживается принципа Open closed.

Оставайтесь на связи

Следующий пост будет на тему Миксины vs компонентов высшего порядка. Если я выдержу графики, он выйдет в июне 2019 года. Шучу 🙂 Ознакомьтесь с полным исходным кодом примера на Github.

Автор: Christian Janker

Источник: //codeburst.io/

Редакция: Команда webformyself.

Метки:

Похожие статьи:

Комментарии Вконтакте: