Ещё одна проблема, ставшая для меня наиболее болезненной — колбеки жизненного цикла в Edge срабатывают асинхронно, во всех остальных браузерах синхронно. На первый взгляд мелочь, но когда на веб-компонентах написаны не просто кнопочки/селекты, а всё приложение (и довольно не маленькое), тогда эта мелочь начинает периодически вылазить в виде разных хитрых багов. И самое неприятное, что баги эти чинятся только оборачиванием нужного куска кода в setTimeout(..., 0), что добавляет ещё больше асинхронности продолжая цепочку багов.
Решал на уровне фреймворка продублировав часть механизмов для Edge и заставив колбеки в нём работать синхронно. Проблему с разным порядком инициализации из-за разного порядка вызова define тоже решил, всё инициализируется в порядке вложенности вне зависимости от других условий.
Ещё одна неприятная мелочь — при перемещении элемента происходит вызов disconnected+connected. Если, например, это сортировка большого списка, каждый элемент которого компонент, то происходит совершенно бессмысленное срабатывание огромной кучи отписок+подписок. Опять же решил на уровне фреймворка: disconnected хоть и срабатывают друг за другом синхронно, но перед ними всеми ставится один nextTick (в этом месте он совершенно не мешает) и если до его срабатывания элемент возвращается в документ, то вместо пары elementDisconnected+elementConnected срабатывает elementMoved. То есть и на перемещение элемента по-прежнему можно отреагировать и лишние отписки/подписки не гоняются туда-сюда.
Проблема с кнопкой в форме легко решается созданием компонента формы автоматически подставляющего невидимую кнопку отправки — пустой класс и три строчки кода в шаблоне.
Проблемы с label не было так как изначально благоразумно отказался от использования ShadowDOM (по этой же причине вряд ли будут проблемы с CSP). Но вот слоты мне понравились, продублировал их в виде компонента без ShadowDOM.
В общем, там ещё много разных шишек набил, зато последние года три кайфую.
Зачем отдельно? Ситуация когда на добавление/удаление какого-либо атрибута нужно и в js как-то отреагировать и какие-то стили добавить у меня происходит регулярно. По вашему же получается нужно так:
А затем для передачи параметра mask="99.99.9999" вы начнёте городить парсер разбирающий класс mask_99.99.9999. А ещё вдруг окажется, что к таким классам из-за значения в нём теперь не прицепить ничего из css как можно было с именем атрибута. Да и пробелы иногда нужно в значении передавать. Не придумывайте себе проблемы.
В случае с веб-компонентами даёт возможность подписываться на изменение любого свойства компонента через attributeChangedCallback, что часто очень пригождается.
Ну так в других ЯП код тоже преобразуется то в машинный, то в инструкции виртуальной машины. Часто в таком виде он тоже выглядит как кракозябры. Просто в других ЯП вам их особо не показывают, а на фронте эти кракозябры нужно регулярно доставлять клиенту и их размер становиться критически важен, вот и полезно иногда посмотреть в них, чтобы убрать лишнее.
Да понятно, что JSON замешан. Что мешало без него? Если по соображениям безопасности не хотите парсить eval-ом, то парсер подобный JSON-у пишется в 100 строк кода. При своём парсере можно и от кавычек в значении избавиться и от лишних фигурных скобок. Что удобнее:
Добавьте атрибуты data-sticky или data-animation (с одиночными кавычками) в ваш элемент, вместе или раздельно.
Задайте параметры (с двойными кавычками внутри) для атрибутов data-sticky и data-animation по следующей схеме (для простоты, взглянем на нее в иерархическом виде).
А почему у атрибутов одинарные кавычки? Что мешает сделать двойные, а одинарные использовать в значении, плюс можно пропускать их для имён полей?
каждый список как элемент? Списки элемента перебираются? Мне кажется лучше each item in list — каждый элемент в списке. Ну или each заменить на repeat|loop.
Пример на TypeScript, показанный выше, это демонстрация реализации более старой версии предложения
Насколько я знаю, для стандарта никогда не было такого предложения как это реализовали в ts. На момент появления декораторов в ts для js предлагался вариант с initializer-ом.
почти совсем не ускорит, в cellx раньше была возможность помечать вычисляемые ячейки как ячейки со статичными зависимостями. То есть зависимости определялись только при первом вычислении и дальше этот механизм полностью отключался. На бенчмарках это вроде и давало какое-то очень скромное ускорение при повторных вычислениях, но там в пределах погрешности было, я пришёл к выводу, что оно просто не стоит каких-то усложнений в коде и плюс нужно такие ячейки ещё самому высматривать. В общем убрал.
let a = cellx(true);
let b = cellx(1);
let c = cellx(() => {
console.log('Compute "c"');
return a() || b();
});
c.subscribe(() => {});
b(2);
// => Compute "c"
a(false);
// => Compute "c"
b(3);
// нет вычисления "c"
При вычислении зависимостей на этапе компиляции они будут прибиты к вычисляемым ячейкам и в последней строке примера вместо 'нет вычисления "c"' будет 'Compute "c"', то есть лишнее вычисление. В конечном счёте на таких лишних вычислениях вы будете терять куда больше производительности. Плюс головная боль при отладке.
С тестированием здесь всё в порядке, просто нативные методы ещё дырки в массивах учитывают (дополнительная операция in), вот и оказываются медленнее.
вот этот полифил с самого начала использую: document-register-element.
Ещё одна проблема, ставшая для меня наиболее болезненной — колбеки жизненного цикла в Edge срабатывают асинхронно, во всех остальных браузерах синхронно. На первый взгляд мелочь, но когда на веб-компонентах написаны не просто кнопочки/селекты, а всё приложение (и довольно не маленькое), тогда эта мелочь начинает периодически вылазить в виде разных хитрых багов. И самое неприятное, что баги эти чинятся только оборачиванием нужного куска кода в
setTimeout(..., 0)
, что добавляет ещё больше асинхронности продолжая цепочку багов.Решал на уровне фреймворка продублировав часть механизмов для Edge и заставив колбеки в нём работать синхронно. Проблему с разным порядком инициализации из-за разного порядка вызова define тоже решил, всё инициализируется в порядке вложенности вне зависимости от других условий.
Ещё одна неприятная мелочь — при перемещении элемента происходит вызов disconnected+connected. Если, например, это сортировка большого списка, каждый элемент которого компонент, то происходит совершенно бессмысленное срабатывание огромной кучи отписок+подписок. Опять же решил на уровне фреймворка: disconnected хоть и срабатывают друг за другом синхронно, но перед ними всеми ставится один nextTick (в этом месте он совершенно не мешает) и если до его срабатывания элемент возвращается в документ, то вместо пары elementDisconnected+elementConnected срабатывает elementMoved. То есть и на перемещение элемента по-прежнему можно отреагировать и лишние отписки/подписки не гоняются туда-сюда.
Проблема с кнопкой в форме легко решается созданием компонента формы автоматически подставляющего невидимую кнопку отправки — пустой класс и три строчки кода в шаблоне.
Проблемы с label не было так как изначально благоразумно отказался от использования ShadowDOM (по этой же причине вряд ли будут проблемы с CSP). Но вот слоты мне понравились, продублировал их в виде компонента без ShadowDOM.
В общем, там ещё много разных шишек набил, зато последние года три кайфую.
Мне кажется дальнейший спор бессмысленнен, вы видете то, что хотите видеть и спорить тут бесполезно. Удачи.
У приведённой страницы есть проблемы с потреблением памяти?
Экономия на спичках.
Чем стало хуже написано выше. Чем лучше то стало?
Если параметры компонента автоматически делать Observable, то да, часто и реактивное программирование находит себе применение:
Зачем отдельно? Ситуация когда на добавление/удаление какого-либо атрибута нужно и в js как-то отреагировать и какие-то стили добавить у меня происходит регулярно. По вашему же получается нужно так:
Да даже если так, зачем создавать себе гемор вот с этим:
?
А можете привести пример когда что-то должно быть именно классом и совсем не смотрится в виде атрибута?
А затем для передачи параметра
mask="99.99.9999"
вы начнёте городить парсер разбирающий классmask_99.99.9999
. А ещё вдруг окажется, что к таким классам из-за значения в нём теперь не прицепить ничего из css как можно было с именем атрибута. Да и пробелы иногда нужно в значении передавать. Не придумывайте себе проблемы.В случае с веб-компонентами даёт возможность подписываться на изменение любого свойства компонента через attributeChangedCallback, что часто очень пригождается.
Ну так в других ЯП код тоже преобразуется то в машинный, то в инструкции виртуальной машины. Часто в таком виде он тоже выглядит как кракозябры. Просто в других ЯП вам их особо не показывают, а на фронте эти кракозябры нужно регулярно доставлять клиенту и их размер становиться критически важен, вот и полезно иногда посмотреть в них, чтобы убрать лишнее.
Да понятно, что JSON замешан. Что мешало без него? Если по соображениям безопасности не хотите парсить eval-ом, то парсер подобный JSON-у пишется в 100 строк кода. При своём парсере можно и от кавычек в значении избавиться и от лишних фигурных скобок. Что удобнее:
или
А почему у атрибутов одинарные кавычки? Что мешает сделать двойные, а одинарные использовать в значении, плюс можно пропускать их для имён полей?
каждый список как элемент? Списки элемента перебираются? Мне кажется лучше
each item in list
— каждый элемент в списке. Ну или each заменить на repeat|loop.Насколько я знаю, для стандарта никогда не было такого предложения как это реализовали в ts. На момент появления декораторов в ts для js предлагался вариант с initializer-ом.
почти совсем не ускорит, в cellx раньше была возможность помечать вычисляемые ячейки как ячейки со статичными зависимостями. То есть зависимости определялись только при первом вычислении и дальше этот механизм полностью отключался. На бенчмарках это вроде и давало какое-то очень скромное ускорение при повторных вычислениях, но там в пределах погрешности было, я пришёл к выводу, что оно просто не стоит каких-то усложнений в коде и плюс нужно такие ячейки ещё самому высматривать. В общем убрал.
Плохая это идея, посмотрите на следующий код:
При вычислении зависимостей на этапе компиляции они будут прибиты к вычисляемым ячейкам и в последней строке примера вместо 'нет вычисления "c"' будет 'Compute "c"', то есть лишнее вычисление. В конечном счёте на таких лишних вычислениях вы будете терять куда больше производительности. Плюс головная боль при отладке.
Зависимости вычисляются при каждом вызове вычисляемой ячейки. А как вам нужно?