Pull to refresh

Comments 74

Жди - щас сюда ворвется главный евангелист и псевдосеньор гно-молла и начнет кричать что вот мол - это мол хорошо, а это, мол, все плохо :D

Хотя, исходя из парадигмы, это должно работать и в его поделии.

Ну и не забарсывайте это дело - вещь шужная и полезная в текущем зоопарке фреймворков.

Уже жду) В любой критике есть доля смысла, а так спасибо за напутствие

Он сейчас в другом треде со мной воюет, дима не придет

Держите оборону! Мы с вами!

Да там не сложно, дешевые набросы и сведение все к тому, что гения никто не понял, вон он 10 лет говно пилит)

Наткнулся на подобный комментарий от него, даже не стал с ним спорить. Это же бессмысленно)

Кстати, тема статьи была чем-то похожа, описывал свою либу для создания веб-компонентов (аналог Lit).

А критика была в том, что веб-компоненты это очень плохо, и не стоит их вообще использовать, но аргументы были пустые и устаревшие)

Очень редко на хабре появляется что-то действительно годное, а не очередная поделка в стиле "я сделал Vue, но хуже и сложнее". Предварительно выглядит круто, занесу ребятам на попробовать.

Решил для себя проверить доступные ли в теневом доме элементы. Оказалось вполне себе доступные как и в лайт-доме.
Попутешествовал по https://zizigy.github.io/CapsuleUI/ с помощью VoiceOver. Вполне себе годно получилось.
Возможно есть какие-то подводные камни, но при беглом осмотре найти не удалось.

Дерево досутпности строится адекватно

Спасибо, исправлю)

Мне больше нравятся CSS-only библиотеки, типа Spectre.css - там еще проще, добавляешь файл и на любом фреймворке заработает, никакой npx не нужен. Правда некоторые компоненты получаются не без хаков, да и как там с доступностью я тоже не уверен.

Ладно, сами напросились…))

Я, признаюсь, посмотрел только код автокомплита, и для себя все понял. До продакшн решения тут как пешком до луны. По большому счету, вы ничего то и не сделали.

Компонент кнопки (button) у меня уже есть в html, нет, реально, ни одной причины делать кнопку в виде веб-компонента. Большая часть остальных, типа Chip, Badge и т.д — делается несколькими строчками цсс. Ну и т.д.

Что реально нужно — автокомплит — маст хэв, только ваш готов процентов на 5, не более. Редкие и не везде нужные, но все же такие вещи, которые на цсс не сделать, например dual-range. То есть, не надо паковать то, что уже есть в хтмл в веб компоненты, надо предлагать то, чего нет.

И хотя я оцениваю решение на условные 5 из 10, в целом — плюсанул, потому что сам веб компоненты люблю, и считаю их недооцененными.

Попробуйте сделать какой-то один, но с полной поддержкой всего. Например, автокомплит должен уметь в множественных выбор, в поиск по опциям, в кастомизацию выбранных опций и самих опций + вести себя для браузера так же как инпут, то есть уметь в валидацию, в :valid, :invalid, :required :empty и тд и тп.

Направление вы выбрали правильное, на мой взгляд.

Автокомплит в процессе, я сначала всю UI либу написал на нативе а потом решил перенести на Lit, чтобы было удобно в поддержке.

Я планирую в целом сделать все для формы чтобы оно корректно работало Select, Autocomplete и прочее, чтобы оно кастомизировалось, так же Modal/ Dialog и прочее.

Спасибо за конструктивный комментарий) Тут все по фактам :3

Спасибо, что делитесь опытом, интересная работа.

Кстати, а почему всё-таки от ваниллы отказались? С какими сложностями столкнулись?

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

Согласен, что плодить новые сущности в виде кастомных компонентов надо тогда, когда можно существенно упростить разметку. Джаваскриптовое поведение можно и через is аккуратно подключить, оставляя понятные всем теги.

через is

Если бы не интернет эксплорер, ой, извините — сафари))

Разработчики сафари наотрез отказались поддерживать эту спеку. Так что её можно не ждать. Плюс многие инструменты для веб-компонентов нарочито игнорируют её. У меня есть смутное подозрение, что рано или поздно её выпилят за ненадобностью.

Вообще вначале я был очень "за" эту спеку, но после нескольких попыток её использовать я понял, что по сути она мне не нужна. Для веб компонентов я чаще всего использую ShadowDOM, а custom built-in elements мне такой возможности не дают. В результате я так ни разу ею и не воспользовался, хотя у ungap project есть хороший полифилл для этого (а ещё я сам такой полифилл писал).

Спасибо! Как-нибудь попробую в следующем пет-проекте с Angular. Хотя я подсел на Microsoft Fluent, благо у них скоро 3.0 для веб-компонентов релизнется, но все равно не против юзнуть что-то новое.

Библиотеку веб-компонентов давно уже пилит гугл https://github.com/material-components/material-web
Это немного не тоже самое. Пилят под материал дизайн и судя по готовности компонентов... пилить будут еще лет 10 до вменяемого состояния.

Спасибо за референс, позаимствую что нибудь)

Её, к сожалению, временно забросили, перекинув основную часть команды на другие проекты. Поэтому может лет 10, а может и никогда

Тем не менее релизы периодически выходят, а значит что-то пилят (может просто баги фиксят, я не вникал)

Ну, maintenance mode же. Конечно что-то фиксят. Но вот Material Expressive уже не дождёмся, как и бо́льшей части компонентов оригинальной спеки

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

Ну стили всегда можно переписать либо сделать тупо такие же стили, в этом ничего сложного) если надо могу сделать

За веб-компоненты однозначно плюс, закинул себе в закладки, чтоб подробнее посмотреть. По поводу автокомплита в браузере, подсказок и прочего советую посмотреть в сторону генерации Custom Elements Manifest и набор инструментов Web Components Toolkit.

Спасибо, обязательно посмотрю на выходных

По SSR можно уточнить?
Nuxt на сервере развернет в базовый html, клиент сразу отрендрит правильно.
С Web Components, вы пишите, все равно отрендрятся на клиенте, да, но сначала как стандартная строка или блок, а потом согласно js, т.е. страница каждый раз при первой загрузке будет дергаться?
По Declarative Shadow DOM, вроде шаблоны нельзя переиспользовать, нужно будет для каждого экземпляра дублировать?

Тут момент я бы сказал будет как в Nuxt когда сервер рендерит блок а потом происходит hydration на клиенте и компонент оживает. Так как в моих компонентах все стили привязываются к тегу, браузер даже до JS может покрасить этот тег, лишь после того как DOM полностью загрузился там уже мы браузеру даем понять что это кастомный элемент. И Если мы что то внутри него рендерим то сервер это не увидит (именно рендерим HTML в нашем компоненте, а не в слоте) Все что рендерим в слоте сервак увидит и все будет хорошо

Исходный код страницы с табами, все отрендерено на сервере
Исходный код страницы с табами, все отрендерено на сервере

Надеюсь ответил на ваш вопрос)

Я немного другое имел ввиду.

Предложим есть компонент календарь, который должен отображаться не инпутом с текущей датой, а табличкой с днями месяца и выделенным текущим днём.

Кастомный компонент если через свойство передавать текущий день, то вначале вообще ничего не отрендрит, а потом дорисует, а если через слот, то сначала напишет просто дату, а потом перерисует.

Типа Nuxt сразу на сервере html с табличкой с днями месяца сделают.

Хотя, наверное, таких случаев не так много и их действительно можно будет в Declarative Shadow DOM запихать.

Спасибо, за библиотеку и пояснения )

Аааа я понял, да тут будет косяк, как раз есть компонент каледнаря в либе и он управляется со стороны, чтобы разработчик сам кнопки делал которые ему нужны, и вот тут возникает действительно проблема потому что ничего отрендерено не будет(

Подскажите пожалуйста, что с обновлениями?

Вот такой кейс, например: добавлена в проект кнопка, поправлены стили и/или скрипт. А потом раз, и появилась в вашей библиотеке еще более крутая (функционально или визуально) кнопка и хочется ее к себе.

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

CLI все сделает за тебя, он перезапишет весь компонент, я предусмотрел этот момент, а так в целом структура использует 1 файл register

Главный файл в котором все подключается
Главный файл в котором все подключается

лайкнул на гитхабе! хорошее дело делаете!
как будут крупные обновления, напоминайте о себе на хабре, хотелось бы поюзать в проектах, но пока компонентов и тем маловато

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

Веб компоненты гвоздями прибиты к DOM, что делает их мертворождёнными.

• Хостовой объект, приаттаченый к документу - это крайне медленно. И ЛТ компилятор тут ничем помочь не может.

• Значениями атрибутов могут быть лишь строки - нужны адовые не совместимые между либами костыли для передачи других типов значений.

• Жизненный цикл компонента начинается лишь в момент аттача хостового элемента.

• Перенос хостового элемента приводит к реаттачу всего поддерева компонент.

• Легко словить конфликт имён компонент между разными либами. И механизмов разрешения этого конфликта нет.

• Единожды зарегистрированный компонент уже нельзя удалить.

• В теневом доме отваливаются все стили - их надо копипастить в каждый теневой дом отдельно. Надо ли говорить, что это тормоза на ровном месте?

• Веб компоненты ничего не знают про пулл реактивность. Хочешь что-то им передать пуш по чём зря через атрибуты и слоты.

Ну в целом по фактам, но есть пару НО

Уж больно категоричны вы что вебкомпоненты "мертворожденны"
Современные браузеры очень хорошо оптимизированы для работы с DOM. Проблемы с производительностью возникают при чрезмерно частых операциях, да это не виртуальный DOM а ShadowDOM, но допустим тот же самый input range, там под капотом вебкомпонент по сути основанный на дивах. Так что в каком то плане это стандартная браузерная технология и даже во Vue/React и прочих фреймах всегда будет доля вебкомпонентов, к примеру есть проекты где юзается Swiper в виде вебкомпонента (не самое хорошее решение но оно вполне себе рабочее)

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

По поводу отвал стилей в теневом доме это да, есть такая проблема, только мое решение не использует теневой DOM, там тупо CSS файлик который биндится на тег и проблем тут быть не может. + Используется ::part в стилях для получения доступа к теневым элементам.

А так в целом я с вами согласен) я же описал это в статье что это нишевая тема и в маленьком количестве проектов это пригодится.

Изначально когда делал это все я понимал что это больше не для фронтов решение, а больше для бекендеров которым лень писать фронт копаться в стилях, использовать JS и все такое, да и хранить в голове названия классов своих для кнопок тоже не кайф, а тут все удобно, VSCode подсказывает аттрибуты + есть генератор этой же VSCode даты прямо в CLI.

Вообщем как то так, короче это решение было больше для проектов на Bitrix / Django или что то вроде, ну и решить проблемы с несколькими фреймами в проекте

хотелось бы массовое решение найти, а не нишевое
lit решает еще часть проблем, но корневые проблемы архитектурные не решить так просто

Это просто тролль, который скопировал чужой комментарий и вообще не разбирается в теме.

  • Проблема про хостовый объект вообще высосна из пальца. Мол каждый элемент имеет внутреннюю реализацию в браузере (хостовый объект), и потому веб-компоненты это плохо. Смешно.

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

  • Да, весь жизненный цикл компонента связан с DOM. А с чем он ещё должен быть связан? Если надо сделать что-то до работы с DOM - используйте другие механизмы.

  • Про перенос элемента - да такой нюанс есть, но это не такая уж частая задача. Также стоимость этой операции не так уж велика на практике. И более того эта проблема уже решена с помощью ConnectedMoveCallback.

  • Проблема с конфликтами решается путем правильных инженерных практик. И чтобы ее поймать надо вообще не следить за тем, что вы подключаете к проекту. И также уже есть пропосал на кастомные реестры.

  • Автор вероятно ничего не слышал про adoptedStyleSheets.

  • Пулл реактивность - непонятно что имеет в виду автор. Комментировать не буду.

Не троль, комент подходит, я с ним согласен, вот и скопировал

Да, весь жизненный цикл компонента связан с DOM. А с чем он ещё должен быть связан?

Не всё нужно отображать

В веб компонентах логика отображения смешивается с обычной логикой работы

  • Пулл реактивность - непонятно что имеет в виду автор. Комментировать не буду.

В реакте push семантика во Vue pull семантика, это же база

В $mol тоже pull семантика

В случае с атрибутами непонятно о каких адовых костылях речь. 

Там только строки, в атрибутах, нет типизация получается, вот это и плохо

Проблема с конфликтами решается путем правильных инженерных практик

Может тогда ci/CD на "правильные" инженерные практики заменим ? Люди же всегда выполняют всё одинаково

adoptedStyleSheets

Есть решение лучше, чем писать стили в js

Тут опять смешение логик получается

Не всё нужно отображать

Веб-компоненты - это просто кастомные DOM-элементы, поэтому и жизненный цикл начинается с connectedCallback.

В веб компонентах логика отображения смешивается с обычной логикой работы

Вот как раз наоборот, веб-компоненты заточены только под отображение и взаимодействие с пользователем через шину событий. Логика, как и при работе с классическими элементами, обычно выносится отдельно.

Там только строки, в атрибутах, нет типизация получается, вот это и плохо

Если работать только через атрибуты, то, конечно, будут строки. И это потому что разметка страницы - это текст. Если же идет речь о том, как передать объект компоненту для его обработки, то пропишите соответствующий метод или свойство в классе веб-компонента, и вызывайте потом в коде.

adoptedStyleSheets - Есть решение лучше, чем писать стили в js

adoptedStyleSheets используется для подключения текстового содержимого в качестве css-таблицы в тень элемента. Причем это делается в connectedCallback. Само же содержимое стиля может быть вынесено в отдельный esm-модуль. Так что смешения тут никакого нет. Да и логика существования самого веб-компонента не нарушена. Потому что веб-компонент - это все-таки про вьюху.

В любом случае все правы по своему, проблема остается, веб компоненты это все таки справедливости ради не Vue.js( это довольно нишевая тема, но на каких нибудь проектах Django / Bitrix, в целом очень даже солидно могут помочь)

Я уверен, что автор предыдущего комментария не разбирается в теме вообще) Типизация поддерживается с помощью плагина для TS - lit-analyzer.

Стили писать на Js не надо, вы можете загрузить CSS файл через import with { type: CSS }, и подключить его в adoptedStyleSheets. Ну, либо использовать сборщик.

Опять же аргумент про конфликты имен очень слабый и автор пытается его защищать возводя в абсурд.

Про push/pull семантики мне по прежнему непонятно, что имеется в виду. В документации упомянутых Фреймворков такого не видел. Но опять же автор считает, что раскрывать свои мысли для смердов - выше его достоинства. Ему удобно кидаться умными абстрактными утверждениями.

Типизация поддерживается с помощью плагина для TS - lit-analyzer.

Там строки парсятся, по сути дублируется работа самого компилятора ts

Для стилей есть три варианта, и у каждого есть недостатки, подробнее тут https://piterjs.org/#!meetup=tx5uqh_fox5zo/speech=62hjim_ogoike

Семантики реактивного програмирования есть разные, это база

Push - мы сами толкаем изменения и пишем для этого код

Pull объекты сами знают об измениях состояния и сами передают туда, куда нужно

Подробнее тут https://habr.com/ru/companies/timeweb/articles/586450/

И не надо в высокомерии меня обвинять, пожалуйста

Вы сделали хоть один проект на веб-компонентах? Мы в команде сделали. И никаких проблем со стилями там нет, все прекрасно работает. Есть нюансы, их просто надо учитывать.

Теперь насчет lit-analyzer, да, там парсится строка. Сам TS не парсит содержимое строк, и какая разница? Главное, что типы выводятся.

Пишу на $mol, там нет таких ньюансов которые нужно учитывать

В мол каждый компонент можно считать веб компонентом, реактивным

Выводить типы из строк - странно, звучит костыльно, вряд-ли оптимизируется jit

При чем тут jit и вывод типов? Типов в runtime нет.

Доклад с piter.js, посмотрел. Доклад поверхностный. Докладчик в теме плавает, например, на вопрос про CSS-переменные и Shadow DOM ответил неправильно и абсолютно запутался в датах, когда были ключевые изменения по стандарту. Лучше посмотрите https://youtu.be/fEhBkSZ15qM

А как у вас в $mol выводятся типы в шаблоне?

Посмотрел видос, в целом понятно почему для веб компонент сделан shadow Dom и отдельный css

Всё же считаю что лучше глобальный css

В $mol нет шаблонов в привычном понимании, есть отдельный DSL

*view.tree

$demo_counter $mol_button
    title <= count \ clicks
    click? <=> increment?

Сборщик превращает его в

export class demo_counter extends $.mol_button {

// то, что из шаблона:
title(): string { ... }             // &lt;= count \ clicks
click(next?: Event): Event | null { ... } // click? &lt;=&gt; increment?

// плюс декларации типов в *.view.d.ts,
// где всё склеено с базовым классом

}

Плюс типы для TS выводит

DSL поддерживает строки

Типизированные и обычные списки

Числа, булеаны, null, ?, ! И что то ещё, кажется

Подробно и кратко тут https://habr.com/ru/articles/724884/

Нет лучше или хуже. Зависит от задачи. Самое главное, что даёт Shadow DOM с точки зрения DX - это строгий API для стилизации компонента: part, CSS переменные и слоты.

То есть ваш DSL не определяет какой тип ожидается для свойства? Проще говоря в момент когда я буду печатать в IDE у меня будет работать автокомплит, если например свойство является enum? Ну, или хотя бы будет IDE подсвечивать ошибку, если я неправильно значение в шаблоне указал?

И еще, а как мне передать функцию, если ваш DSL поддерживает только строки и списки? Вы же критиковали веб-компоненты за это же)

Есть расширения для vscode, zed

Есть tree sitter, Lsp

Можно и для jetbrains написать на основе lsp

Функции передавать не нужно, методы переопределяем в *.TS файлах

Поддерживаются не только списки и строки

Ну, вот хочется мне передать анонимную функцию в свойство.

Но хорошо допустим у меня есть метод, и есть событие которое испускает компонент.

Будет ли проверка, что аргумент метода совпадает по типу с испускаемым событием?

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

по поводу проверки, не знаю если честно, надо посмотреть какие типы будут

допустим такой код
$my_app $mol_page
sub /
<= Add $mol_button_minor
click? <=> add_submit? null

получит такие типы
type $mol_button_minor__click_my_app_1 = $mol_type_enforce&lt; ReturnType&lt; $my_app['add_submit'] &gt; , ReturnType&lt; $mol_button_minor['click'] &gt; &gt; export class $my_app extends $mol_page { add_submit( next?: any ): any Add( ): $mol_button_minor sub( ): readonly(any)[] }

и такой js

($.$my_app) = class $my_app extends ($.$mol_page) { add_submit(next){ if(next !== undefined) return next; return null; } Add(){ const obj = new this.$.$mol_button_minor(); (obj.click) = (next) => ((this.add_submit(next))); return obj; } sub(){ return [(this.Add())]; } }; ($mol_mem(($.$my_app.prototype), "add_submit")); ($mol_mem(($.$my_app.prototype), "Add"));


тут нету вроде как, но можно руками переопределить в view.ts
add_submit(next){ if(next !== undefined) return next; return null; }

и прописать типы


Понятно, в плане DX тут тоже есть проблемы в шаблонах.

view.tree специально спроектирован не тьюринг полным, вся логика в *.ts
cмешения нет


дерево компонент + логика + стили
дерево компонент + логика + стили

В случае если Shadow DOM не работает, это работает на Shady DOM? или какие там сейчас фолбеки?

Вообще сейчас Shadow DOM поддерживается всеми браузерами кроме IE, и Shady DOM не используется в библиотеке

(Вообще это не точная информация, может быть Lit под капотом использует)

Ну тогда (polymer) тоже оно всеми уже поддерживалось, но у клиентки был ноут со старой mac os, потому, что она боялась обновиться, что бы не слетел пиратский фотошоп))) Так что работает во всех новых факт, но стоит учитывать, что даже если 1% пользователей отвалится, в деньгах это может быть большой кусок)

Lit не использует полифиллы из коробки. Если нужна поддержка в легаси браузерах, то нужно использовать Lit2 и самому подключить полифилл.

Отличный проект, спасибо!

Есть проблемы с цветами текста на кнопках:

Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:109.0) Gecko/20100101 Firefox/115.0

В хроме такая же фигня (Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36)

Понимаю, не самые свежие браузеры, но это максимум, что можно установить на этот макос)

скорее всего проблема в том что используется свежая реализация светлой темы и темной темы для CSS, light-dark, возможно она не поддерживается, спасибо за комментарий я посмотрю в чем проблема

Сильно смело использовать свежие свойства и забыть посмотреть насколько они поддерживаются в популярных браузерах. Лучше рассмотреть возможность дописать фоллбеки

Не знаю как бы сказать но я посмотрел на свойства и как они поддерживаются

Просто не думал что кто то еще сидит на старых браузерах, опять же 115 firefox не такой уж и старый если сравниваем IE, но все таки, я думаю можно вполне использовать, да и переписать стили с light-dark на :root.dark, :root.light вообще не так уж и сложно учитывая что все переменные в одном файле

Привет, как с поддержкой Svelte? 🤔

Привет, не проверял, хороший вопрос надо будет проверить, но скорее всего все должно работать так как все работает примитивно

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

Хороший проект, не забрасывайте, на lit не так много ui либ, я знаю shoelace и spectrum web components от adobe. Концепция у вас крутая, особенно для тех, кто делает не совсем стандартные для веба интерфейсы. Добавил в закладки и достану когда придет время ковырять интерфейсы в своем пет проекте. Сейчас там хаос из разрозненных lit компонентов. Из пожеланий: компонент tree (в идеале с dnd перетаскиванием, пробежался по вашим статьям и видел что вы уже это реализовывали на vue). Кстати вроде на ts пишете, тут решили отказаться в пользу упрощения?

Конкретно сам CLI написан на TS, а сами компоненты на нативном JS для того чтобы можно было использовать данное решение без сборки. Специально указан ХАБ битрикса потому что по сути появился проект где была у меня такая необходимость в вебкомпонентах, и выполнять сборку через bitrix/cli или vite вообще не хотелось, в будущем планирую добавить d.ts

По поводу Tree компонента уже есть идеи, я планировал сделать что то вроде модуля с dnd чтобы можно было реализовывать DnD через HTML теги просто с минимальным JS, но это слишком набудущее, DnD потом будет.

Просто в планах взять сначала переписать свою первую либу про которую вы упомянули на нативный JS/TS + добавить selection area (ну типо окно как на винде когда юзер зажимает и область появляется и все элементы которые туда попали можно драгать)

Как то так

Для Lit подойдут как любые библиотекии веб-компонентов (сделанные на любом фреймворке или без), так и одиночные веб-компоненты. Обычно достаточно загуглить «x web component», где x — название того, что вам нужно. Посмотреть подборку библиотек веб-компонентов можно в этом репозитории. Ещё недавно релизнулись Web Awesome, наследник Shoelace от тех же авторов.

Sign up to leave a comment.

Articles