Хабрахабр

[Из песочницы] Прокачиваем разработку на Vue с помощью паттернов: HOC

А вот Vue-разработчики его как-то обходят стороной. Паттерн HOC (Higher Order Component) очень популярен у React-разработчиков. Попробуем разобраться в этом. Очень зря.

Что такое HOC?

Компонент высшего порядка (HOC)  —  это функция, которая принимает существующий компонент и возвращает другой компонент, который оборачивает первоначальный, добавляя новую логику.

image

HOC vs mixins

Они так же добавляют новый функционал компонентам. Возможно, многие зададутся вопросом, зачем использовать HOC, когда есть примеси? Что может HOC чего не умеют примеси?

Сперва вспомним, что такое примеси во Vue (определение взято из документации Vue):

Объект примеси может содержать любые опции компонентов. Примеси (mixins)  —  это гибкий инструмент повторного использования кода в компонентах Vue. При использовании компонентом примеси, все опции примеси «подмешиваются» к собственным опциям компонента.

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

Примеси “подмешиваются” при объявлении компонента  —  любой экземпляр компонента будет содержать их.
С помощью HOC мы оборачиваем экземпляр компонента не меняя сам компонент, а создавая новый, в том месте, где это требуется. Но различие кроется в самом принципе работы HOC и примесей. Благодаря этому мы уменьшаем связанность кода, делаем его более читабельным и гибким. Это значит, что мы влияем только на тот кусок кода, где мы его используем.

HOC чем-то напоминает шаблон проектирования decorator.

Создание HOC

Давайте разберём всё это на примере. Ну что ж.

Итак, у нас есть компонент кнопка:

image

Мы можем это сделать через примеси, подмешав код для логирования в компонент кнопки, а потом в нужном месте включать или отключать логирование через какое-нибудь свойство компонента. Через какое-то время нам вдруг понадобилось логировать нажатие некоторых кнопок (но не всех). А если такого функционала очень много? Но согласитесь, это не очень удобно? Одна ошибка  —  и все кнопки могут перестать работать корректно.

Мы просто обернём в некоторых местах кнопку соответствующим HOC. HOC в данном случае будет отличным решением.

Пришло время познать HOC на практике.

Шаг 1. Создаём HOC фукнкцию

Так создадим же такую функцию. Мы помним, что HOC  —  это функция, которая принимает на вход компонент и возвращает другой. Назовём её withLoggerButton.
Именование HOC-функций принято начинать с with  — это своего рода опознавательный знак HOC’ов.

image

В render-функции мы используем изначальный компонент, но с одним изменением — добавляем событие на клик по DOM-узлу, вывод в консоль надписи clicked. Получилась функция, которая принимает на вход компонент Button, а потом возвращает новый компонент.

Если вы не поняли, что тут происходит, что такое h и context, то сперва прочитайте документацию vue по работе render-функций.

мне не требуется состояние. В текущем примере я использовал именно функциональный компонент, т.к. Никто вам не запрещает возвращать обычный компонент вместо функционального, но не забывайте, что функциональные компоненты намного быстрее обычных.

Шаг 2. Используем HOC

Теперь с помощью полученной функции просто создадим новый компонент.

image

Осталось дело за малым — подключить полученный компонент там, где нам нужно логирование нажатий.

Итоговый пример:

Композиция

Всё это конечно здорово, но что делать, если нужна кнопка, которая не только логируется, но и выполняет ещё какое-то действие?

Мы оборачиваемости один HOC в другой. Всё просто. Мы можем так смешать сколько угодно HOC-ов.

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

Он используется в основе множества библиотек. HOC  —  это простой, но в то же время очень мощный паттерн. Используйте его с умом и ваши приложения на Vue станут намного более опрятными и по настоящему гибкими.

Кросс-пост

Теги
Показать больше

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

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Кнопка «Наверх»
Закрыть