Pull to refresh

Comments 34

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

в LitElement вертска пишется прямо в джаваскрипт код, что нарушает инженерный принцип разделения ответственностей и лишает разработчика гибкости получаемой от использования нативных шаблонов. Например, с помощью веб-компонентов я легко могу сделать систему, которая будет поддерживать скины и кастомизацию не только за счет изменения стилей, но и самого лейаута.
UFO just landed and posted this here
на мой взгляд это скорее поветрие, они обожглись с Polymer, когда все вроде было сделано не плохо, но за счет HTML Imports получался код в верстке и маятник качнуло в другую крайность, уже утвержденную популярностью реакта.
UFO just landed and posted this here
отдельные браузерные вендоры от импортов отказались «на отрез», поэтому в стандарты W3C они не пошли, а команда полимера на тот момент уже вовсю готовила 3ю версию фреймворка серьезно базировавшуюся на механизме импортов и все дальнейшее развитие тоже пришлось отменить в пользу LitElement
UFO just landed and posted this here
В 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 совсем

UFO just landed and posted this here
атрибуты это строки, да, и в DOM вы можете зарендерить строку, но это не означает, что браузер хранит все в виде текстового файла. Для создания можно использовать document.createElement или просто конструкторы и аттрибуты. В дереве есть и индексация, по айди выборка быстрее, чем селектором или даже элемент можно сразу получить из глобального пространства, есть и типизация самих элементов за счет того, что за каждым элементом вы можете закрепить свой тип-класс, и это все позволит просто и изящно структурировать код, так что-бы не было огромных портянок с вермишелями.
UFO just landed and posted this here

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

UFO just landed and posted this here

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


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

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

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

— и в итоге вы получите толстый оверхед в js как в React.
UFO just landed and posted this here
UFO just landed and posted this here
Sign up to leave a comment.

Articles