Научитесь кодировать свой собственный с помощью TypeScript и Generics!
В мире JavaScript (и, следовательно, TypeScript) шаблон Composite - это тот шаблон, который вы, вероятно, использовали, даже не осознавая. В конце концов, DOM можно рассматривать как древовидную структуру, заполненную сущностями, использующими один и тот же интерфейс. И если мы перейдем на уровень абстракции в React или Vue, у вас также будет древовидная структура, заполненная сущностями, называемыми «компонентами», совместно использующими общий API.
Не думаете ли вы, что тогда важно понимать этот шаблон, который так часто используется во многих случаях? Давайте начнем прямо сейчас.
Составной узор объяснил
Этот шаблон - один из самых простых, поскольку действительно есть один компонент, о котором вам нужно беспокоиться: композит.
Композит - это структура, образованная из других композитов, вместе создающая древовидную структуру… композитов (рекурсия, да!). Вы можете думать об этом как о структуре каталогов, где в корневом каталоге могут быть другие каталоги внутри него, но также могут быть текстовые файлы, изображения и другие типы файлов.
Это композит. И точно так же вы можете представить внутреннюю структуру папок, если вы создавали ОС. Но как реализовать такую концепцию? Что такое «композит»?
По сути, составной элемент - это структура, которую вы можете назначить другим структурам или которая может содержать другие структуры того же типа. Конечно, JavaScript не очень хорош, когда дело касается типов, и применение общего API может стать проблемой, поэтому вместо этого мы используем TypeScript.
Написание нашего составного компонента
Вместо того, чтобы показывать простое объявление класса, я буду использовать бит в своем примере, чтобы показать вам, как быстро создать совместно используемый составной компонент, который вы можете использовать в своих проектах.
Если вы не знаете, что такое Bit, вы можете ознакомиться с этой вводной статьей, которую я написал, в которой описаны его основы:
Структура проекта очень проста, просто создайте папку для проекта и внутри нее папку под названием «композитный». В этой папке мы создадим composite.ts
файл, который будет содержать наше определение, и файл index.ts
, который будет экспортировать наше определение и действовать как основная точка входа.
Соответствующий код внутри composite.ts
следующий:
Я экспортирую две вещи:
- Определение универсального интерфейса для нашего составного класса.
- И собственно общий составной класс.
Я использую здесь Generics (обратите внимание на <T>
в определении), чтобы код можно было использовать повторно. Вы через минуту поймете, что я имею в виду.
Логика внутри класса на самом деле не такая сложная, вы можете добавить в нее столько сложности, сколько вам нужно, но для того, чтобы показать вам пример, у меня просто есть простой метод addChild
, который заботится о добавлении как можно большего количества дочерних составные компоненты по своему усмотрению. И еще у меня есть traverse
метод, потому что я считаю важным показать хотя бы один способ перебора компонентов. Ведь это не простой список элементов, это древовидная структура.
Метод обхода, который я закодировал, просто будет идти по принципу «сначала дочерний», а затем в качестве последнего элемента он займется корневым компонентом. А под «снастью» я имею в виду, что он применит к нему полученную функцию.
Теперь, когда этот код находится в вашем файле и бит уже установлен, вы можете быстро запустить следующую строку в корне вашего проекта:
$ bit init --harmony
Теперь измените только что созданный файл workspace.jsonc
, чтобы он использовал среду Node.js (если вы кодируете не с помощью Node, вы можете настроить этот шаг по своему усмотрению). Для этого откройте файл, найдите ключ teambit.workspace/variants
и убедитесь, что он выглядит так:
"teambit.workspace/variants": { "*": { "teambit.harmony/node": {} } }
Теперь просто добавьте компонент, который будет отслеживаться Bit:
$ bit add composite/ --namespace components
И установите Jest, чтобы мы также могли создать несколько тестов для нашего кода:
$ bit install jest
Установив Jest (обратите внимание, что я еще не использовал NPM), создайте в вашей composite
папке новый файл с именем composite.spec.ts
и добавьте следующий код:
Я тестирую там 2 вещи, возможно, вы могли бы придумать более интересные крайние случаи:
- Я тестирую простой вызов
addChild
- И я тестирую логику обхода.
Но обратите внимание на второй тест, обратите внимание, как я использую Generics, определяя настраиваемый тип с именем HouseComponent
. У него есть только одно свойство, но я использую его, чтобы добавить цвета своей кровати и дивану. Я определяю набор настраиваемых свойств, а затем использую их как часть создания экземпляров моих композитов, превращая мои «общие композиты» в конкретный.
Вы можете использовать один и тот же код со своими собственными настраиваемыми типами и беспокоиться только о настраиваемых свойствах, остальная логика останется прежней. Я имею в виду, что вы можете легко создавать компоненты, называемые «div» и «body», и заставлять их использовать настраиваемые реквизиты с такими атрибутами, как id
или style
, звучит знакомо? Вы воссоздали упрощенную версию модели DOM, только добавив в нее пользовательский тип. Мощный!
Чтобы протестировать наш код, просто запустите:
$ bit test
В результате вы должны увидеть что-то вроде этого:
$ bit test - loading bit... - loading aspects... - running command test [pattern]... testing total of 1 components in workspace 'my-workspace-name' testing 1 components with environment teambit.harmony/node PASS components/composite/composite.spec.ts Composite component √ should correctly add a component to the children list (2 ms) √ should iterate over the full composite children-first (1 ms) Test Suites: 1 passed, 1 total Tests: 2 passed, 2 total Snapshots: 0 total Time: 2.16 s Ran all test suites. tested 1 components in 3.712 seconds.
К настоящему времени вы должны были заметить несколько вещей:
- Я пока вообще не использовал NPM, и если вы разработчик на Node.js, вам может быть интересно: что с этим?
- Несмотря на то, что я установил Jest, я никогда не настраивал его и не указывал, какие файлы я хочу протестировать при запуске
bit test
.
В этом сила Bit, которая отвлекает вас от основных операций. Используя Bit, мне не нужно было беспокоиться о выборе диспетчера пакетов (по умолчанию Bit использует pnpm, но вы этого не заметили, не так ли?) Или о настройке Jest, он просто работает. Фактически, по умолчанию он знает, что каждый файл в папке компонента, заканчивающийся на .spec.ts
, является тестовым файлом, который должен быть протестирован Jest.
Круто?
Экспорт вашего кода для всего мира
В качестве дополнительного бонуса вы можете быстро экспортировать свой код и поделиться им со своей командой (или командами).
Во-первых, вам нужно пометить свой компонент или, другими словами, указать ему версию:
$ bit tag --all 0.0.1
Затем убедитесь, что вы вошли в систему на своем терминале, если нет, введите:
$ bit login
Вы будете перенаправлены на bit.dev, где сможете войти в систему (или зарегистрироваться, если еще не сделали этого).
После входа на веб-сайт вам нужно будет создать коллекцию (выбирая версию Harmony, когда ее спросят) под названием «компоненты» (поскольку это было пространство имен, которое мы выбрали ранее), а затем отредактировать файл workspace.jsonc
, чтобы он имел ключ defaultScope
. быть "[your username].components"
, в моем случае это было бы "deleteman.components"
.
После этого экспортируйте свою работу с помощью:
$ bit export
Вы можете увидеть конечный результат здесь: https://bit.dev/deleteman/components/components/composite
Заключение
С композитным компонентом очень весело работать, и его очень легко кодировать. Приглашаем вас импортировать мой общедоступный компонент, расширить его и использовать по своему усмотрению. Возможно, вы захотите добавить дополнительные методы для поиска определенного узла или чего-то в этом роде, но это только начало.
Что касается использования TypeScript, в данном случае я считаю очень полезным то, что я смог быстро создать этот прототип, не беспокоясь об установке чего-либо, НО бит. Фактически, я написал все это на TypeScript, и мне даже не пришлось беспокоиться об установке TypeScript на мою машину, это дико!
Вы тоже поклонник паттерна Composite? Оставьте комментарий и поделитесь своим любимым шаблоном дизайна, давайте устроим старый добрый конкурс и посмотрим, кто победит!
Создавайте что-нибудь из независимых компонентов
Попрощайтесь с монолитными приложениями и оставьте после себя слезы их развития.
Будущее за компонентами; модульное программное обеспечение, которое быстрее, масштабируемее и проще в сборке. Инструменты OSS, такие как Bit, предлагают отличные возможности разработчика для создания независимых компонентов и составления приложений. Многие команды начинают с создания своих дизайн-систем или микро-интерфейсов с помощью общих компонентов. Попробуйте →