у меня такое проксирование даже через две обёртки случалось довольно редко, хотя приложения делал очень не маленькие. В любом случае даже через глобальный объект можно общаться событиями не создавая жёсткой связи.
UPD: глобальным объектом в этом случае обычно делается корневой компонент приложения который виден из всех компонентов как this.ownerComponent (или this.rootComponent).
Описанный подход создаёт жёсткую связь от подчинённого компонента к владеющему компоненту. Нормально в обратном направлении — владелец вызывает метод подчинённого, причём для этого не нужен какой-то глобальный объект, ведь владелец знает своих подчинённых, если же подчинённый лежит в каком-то компоненте-обёртке, то на нём (компоненте-обёртке) создаётся проксирующий метод. В описанном же варианте периодически будут возникать ситуации, когда казалось бы универсальный компонент перемещается в другое место с полным удалением бывшего владельца и от этого ломается. Правильный подход — использование всплывающих событий — подчинённый компонент просто эмиттит событие о том, что с ним случилось, если какому-то предку вверх по иерархии нужно как-то на это реагировать, он подписывается на это событие. Куда бы не перемещался подчинённый компонент, он не ломается, тк. связь не жёсткая. Если два компонента никак не вложены друг в друга и всё равно должны взаимодействовать, то взаимодействие делается через общего для обоих предка, который подписывается на событие одного компонента и вызывает метод другого.
При том, что нативные методы не в курсе, что тест на массивах без дырок и операцию in выполняют всегда. Описанному в статье методу оптимизации нативных методов уже лет так восемь минимум.
Ещё одна проблема, ставшая для меня наиболее болезненной — колбеки жизненного цикла в 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-ом.
у меня такое проксирование даже через две обёртки случалось довольно редко, хотя приложения делал очень не маленькие. В любом случае даже через глобальный объект можно общаться событиями не создавая жёсткой связи.
UPD: глобальным объектом в этом случае обычно делается корневой компонент приложения который виден из всех компонентов как
this.ownerComponent(илиthis.rootComponent).Описанный подход создаёт жёсткую связь от подчинённого компонента к владеющему компоненту. Нормально в обратном направлении — владелец вызывает метод подчинённого, причём для этого не нужен какой-то глобальный объект, ведь владелец знает своих подчинённых, если же подчинённый лежит в каком-то компоненте-обёртке, то на нём (компоненте-обёртке) создаётся проксирующий метод. В описанном же варианте периодически будут возникать ситуации, когда казалось бы универсальный компонент перемещается в другое место с полным удалением бывшего владельца и от этого ломается. Правильный подход — использование всплывающих событий — подчинённый компонент просто эмиттит событие о том, что с ним случилось, если какому-то предку вверх по иерархии нужно как-то на это реагировать, он подписывается на это событие. Куда бы не перемещался подчинённый компонент, он не ломается, тк. связь не жёсткая. Если два компонента никак не вложены друг в друга и всё равно должны взаимодействовать, то взаимодействие делается через общего для обоих предка, который подписывается на событие одного компонента и вызывает метод другого.
При том, что нативные методы не в курсе, что тест на массивах без дырок и операцию in выполняют всегда. Описанному в статье методу оптимизации нативных методов уже лет так восемь минимум.
С тестированием здесь всё в порядке, просто нативные методы ещё дырки в массивах учитывают (дополнительная операция 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-ом.