Как стать автором
Обновить

Комментарии 34

Для чего так утруждать руки набором кода? Есть же lit element. Всё это уже прожевано там.

в LitElement вертска пишется прямо в джаваскрипт код, что нарушает инженерный принцип разделения ответственностей и лишает разработчика гибкости получаемой от использования нативных шаблонов. Например, с помощью веб-компонентов я легко могу сделать систему, которая будет поддерживать скины и кастомизацию не только за счет изменения стилей, но и самого лейаута.
НЛО прилетело и опубликовало эту надпись здесь
на мой взгляд это скорее поветрие, они обожглись с Polymer, когда все вроде было сделано не плохо, но за счет HTML Imports получался код в верстке и маятник качнуло в другую крайность, уже утвержденную популярностью реакта.
НЛО прилетело и опубликовало эту надпись здесь
отдельные браузерные вендоры от импортов отказались «на отрез», поэтому в стандарты W3C они не пошли, а команда полимера на тот момент уже вовсю готовила 3ю версию фреймворка серьезно базировавшуюся на механизме импортов и все дальнейшее развитие тоже пришлось отменить в пользу LitElement
НЛО прилетело и опубликовало эту надпись здесь
В 3-м Полимере основным нововведением как раз был переход от html-импортов к ES-модулям. Вполне закономерно и грамотно. Но Lit — оказался быстрее… Я лично не сравнивал, но судя по блогу разрабов — это был основной аргумент перехода. Сейчас Polymer — это скорее экосистема, чем библиотека. И LitElement входит в нее. Но из-за всех этих метаний, веб-разработчики отвернулись от этого минизоопарка, хотя и стоит отдать должное сообществу Полимера — они сделали очень многое для внедрения новых стандартов.
Принцип разделения ответственности не определяет критерии разделения. То есть вы сами вольны делить свой код в согласии с вашими приоритетами и в в случае с LitElement никаких особых проблем с этим нет. Как нет их и с возможностью поддержки скинов и другой кастомизации: вам доступны те-же самые пользовательские свойства CSS и кастомные атрибуты. Но мне самому LitElement не нравится, более всего потому, что вместо того, чтобы быть альтернативой реакту, он пошел той-же скользкой дорожкой на поводу у фанатов функциональщины. И из за этого, к примеру, он медленнее, чем мог бы быть.
у меня был кейс angular material/cdk, когда мне надо было сделать другой пейджер и свой фильтр, легко переопределял классы и использовал свои шаблоны, менял на совершенно иной принцип работы и заодно локализовал, не уверен, что такое было бы возможно с фреймворком предполагающим прямую линковку и хардкод верстки
Но в Lit шаблон — это же просто js-строка, которую вы можете генерить на лету, как вам угодно, или брать целиком из различных источников. Совсем не обязательно что-то хардкодить.
как я понимаю, из источников не получится подгрузить асинхронно, т.е. по сети (динамически), только если предзагрузить шаблоны до инициализации самих компонентов и в этом случае конвертация обратно в строку тоже будет лишней. Единственный вариант тут будет дорендеривать шаблоны в какие-нибудь слоты, но это все будет запутаннее чем даже продолжать наворачивать html-строки в коде, поэтому никто в сторону шаблонов отделенных от кода и не посмотрит.
Не совсем понял вашу проблему, но мне почему-то кажется что это решается проще. В любом случае, для работы с темами, скинами и вариантами отображения мне всегда хватало CSS-переменных и кастомных атрибутов. Если изменения компонента должны быть более глобальными — поможет создание отдельного компонента или старое доброе наследование.
если у вас шаблоны отдельно, то их надо загружать, загружать их надо будет по сети, особенно если вы имеете дело с SPA и некоторой модульной архитектурой на приличном размере, а по сети значить асинхронный запрос с отложенным результатом, т.е. это надо будет делать либо до инициализации/рендера самих компонентов, либо как-то хитрить. Видимо так же нетривиально, как и в случае если вам пейджер с контролами < — -> надо будет перескинить на пейджер с пейджанацией 1 2 3 используя только css. Насчет наследования я не уверен, тут штука в том, что компоненты могут находится в тесном взаимодействии друг с другом которое будет полагаться на конкретные класс, а не их даже наследники. Например у вас есть такой лейаут:

<grid>
  <filter></fitler>
  <table></table>
  <pager></pager>
</grid>


если разработчик реализовал прямое связывывание всех этих компонентов (хардкод) без возможности подменить скажем pager, своей реализацией, с доработкой такого кода могут быть проблемы, в то же время если он разрабатывал уважая необходимость выносить верстку-лейаут в отдельные шаблоны, эти шаблоны вы переопределить скорее всего сможете.
Не совсем понимаю зачем загружать шаблоны отдельно… Почему сразу нельзя создать несколько шаблонов и передавать в render нужный? Почему нельзя переопределить класс-конструктор?
отдельно загружать придется потому что они структурированы отдельно, потому что все вместе их будет неудобно поддерживать даже может более неудобно, чем если они захардкожены в джаваскрипте. Можно конечно склеить, но тогда либо опять же все придется загружать и разбирать, а их может быть очень много либо полагаясь на запрашиваемый роут, но и в этом случае при переходе на другой, надо будет загрузить шаблоны для добавляемых элементов. Переопределить что-то и встроить в инфраструктуру можно восновном когда разработчики фреймворка и решения на нем об этом как-то подумали, но на деле я такой уровень видел только в ангуляре и то вот у него конфигурирующие директивы вынесены в аннотации, что осложняет решение задачи переопределения, т.е. вы можете у своего наследника сделать другой темплейт, но переконфигурировать имеющийся компонент на использование вашего темплейта задача уже нетривиальная.
Если вы код контролируете — проблемы нет вообще. Если не контролируете — тогда не понятно как именно вы интегрируетесь. Почему нельзя сделать так:
    class MyEl extends HTMLElement {

      render(tpl) {
        this.$.innerHTML = tpl;
      }

      constructor() {
        super();
        this.$ = this.attachShadow({
          mode: 'closed',
        });
        this.render('Original Element');
      }
    }
    
    class MyExtendedEl extends MyEl {
      constructor() {
        super();
        this.render('Extended Element');
      }
    }

    if (someFlag) {
      MyEl = MyExtendedEl;
    }

    window.customElements.define('my-el', MyEl);

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

Про производительность интересно. Что могли в lit-element сделать по-другому, чтобы стать быстрее?

Для ускорения первичной отрисовки, могли исключить этап обработки строки шаблона в js-рантайме для привязки данных перед парсингом в DOM. Вариант с клонированием шаблона из template-контейнера и заполнением его данными, но уже через DOM API работает быстрее почти в 2 раза, судя мо моим тестам. Даже если template-контейнер (элемент ) создавать динамически из той-же js-строки и хранить в памяти. Для ускорения рендера изменений — могли бы не делать этого асинхронно. Синхронный рендер работает быстрее на 20% примерно (браузер умный, он не перерисовывает документ сразу если изменение элементов идет в цикле). Как то так.

Насколько я понимаю, предлагается класть шаблон элемента в <template> тэг и тем самым немножечко сэкономить, избавив lit-html от этапа инициализации. Как я вижу из исходников lit-html, они кешируют результат, поэтому затраты на создание шаблона одноразовые, от числа ре-рендеров не зависят.


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


Синхронное обновление свойств – это проклятие веб-компонентов в целом. Свойства обновляются поштучно, и изнутри компонента вы не можете предугадать, закончили вам передавать свойства или нет. Я уже писал об этом подробнее. И в статье Рича Харриса, почему Svelte не использует веб-компоненты, об этом тоже есть. В общем, lit-element тут не одинок, все веб-компоненты этим страдают.

Я прекрасно помню ту вашу статью и нахожу ее тезисы ошибочными. В прошлый раз у нас не получилось какого-то особо конструктивного диалога, не думаю что нам стоит тратить время на это снова. Мне лучше потратить время на документацию своего велосипеда и выкатить статью про него. К сожалению пока не получилось выделить на это окно в рабочем графике, но я это сделаю в любом случае.
>> то начинаются другие проблемы

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

>> С ленивой загрузкой компонентов тоже непонятно как быть

с ленивой загрузкой в веб-компонентах ситуация лучше всех, т.к. для браузера динамически дорендеренный <my-custom-element> преобразуется в ваш кастомный компонент без особенных препятствий и с выполнением полагающихся хуков

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

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

Собственно, lit-html это сейчас и делает. Если я правильно понял i360u, то он предлагает следующий уровень оптимизации — вынести это из JS совсем

НЛО прилетело и опубликовало эту надпись здесь
атрибуты это строки, да, и в DOM вы можете зарендерить строку, но это не означает, что браузер хранит все в виде текстового файла. Для создания можно использовать document.createElement или просто конструкторы и аттрибуты. В дереве есть и индексация, по айди выборка быстрее, чем селектором или даже элемент можно сразу получить из глобального пространства, есть и типизация самих элементов за счет того, что за каждым элементом вы можете закрепить свой тип-класс, и это все позволит просто и изящно структурировать код, так что-бы не было огромных портянок с вермишелями.
НЛО прилетело и опубликовало эту надпись здесь

А как это будет работать на практике? Возьмем, к примеру, вот этот самый блок комментариев на Хабре. Каким образом вы бы собрали из DOM его состояние, чтобы реализовать редактирование комментария, например?

НЛО прилетело и опубликовало эту надпись здесь

Да, есть такая библиотека, Stimulus, работает именно как вы и описываете. Я даже опубликовал на Хабре перевод их анонса.


Однако, в массы такой подход не идет почему-то.

НЛО прилетело и опубликовало эту надпись здесь
Идея о том, что DOM может быть основным хранилищем данных, поскольку он в любом случае их хранит, имеет под собой веские основания. Тем более, что помимо данных, пришедших, к примеру с сервера, есть еще положение скролла, элементы в фокусе и так далее, то есть все то, чего нет обычно в реализациях внешних хранилищ, и DOM, вроде как, имеет больше прав называться «стейтом». Однако есть одно большое «но»: DOM — это древовидная структура, а ваши реальные данные — чаще являются графом. И если любое дерево может быть представлено в виде графа, то граф в виде дерева — уже нет. На практике это означает, что если у вас есть, к примеру, некая зависимость в интерфейсе от того, залогинен пользователь или нет — вы не можете рассчитывать на достоверность этого флага в одной из нод вашего DOM, пока вы не выделите для хранения этого значения единый «источник правды». Насколько я помню, именно об это обожглись, в свое время, разработчики Facebook, перед тем как начали пропагандировать flux-архитектуру.

Все это можно сделать даже без кастом-элементов, на старых стандартах.

— и в итоге вы получите толстый оверхед в js как в React.
НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории