В настоящее время jQuery является де-факто библиотекой для работы с DOM. Она может использоваться вместе с популярными MV* фрэймворками (такими как Backbone), имеет множество плагинов и очень большое сообщество. С другой стороны JavaScript становится все популярнее и многие разработчики начинают интересоваться как работают стандартные API и когда можно просто их использовать, не добавляя дополнительную библиотеку.
В поздние дни работы с jQuery я начал замечать разные проблемы с этой библиотекой. Большинство из них основопологающие, поэтому не могут быть исправлены без потери обратной совместимости, что, конечно, важно. Я, как и многие другие, продолжал использовать библиотеку какое-то время, встречаясь с надоедливыми причудами каждый день.
Затем Daniel Buchner создал SelectorListener, и родилась идея live расширений. Я начал подумывать о создании набора функций, который позволит создавать ненавязчивые и независимые компоненты DOM, используя лучший подход. Задача была сделать обзор существующих решений и создать более понятную, тестируемую, маленькую, но в то же время самодостаточную библиотеку.
Идея live расширений способствовала разработке проекта better-dom, хотя кроме него имеются другие интересные особенности, которые делают библиотеку уникальной. Давайте сделаем их беглый обзор:
В jQuery существует понятие live событий. За кулисами они используют event delegation чтобы обрабатывать существующие и будущие элементы. Однако во многих случаях требуется большая гибкость. Например, если виджет должен при инициализации добавить дополнительные элементы в дерево документа, которые должны взаимодействовать или замещать существующие, live события не работают. Чтобы решить проблему я представляю live расширения.
Цель — объявить расширение однажды, и после этого оно должно работать для будущего контента независимо от сложности виджета. Это важная особенность, поскольку позволяет создавать веб-страницы декларативно, поэтому хорошо подходит для AJAX приложений.
Рассмотрим простой пример. Допустим, наша задача реализовать полностью кастомизируемую всплывающую подсказку. Псевдоселектор
Наш тултип теперь можно стилизировать с помощью селектора
Однако самое интересное начинается, когда новые элементы с атрибутом
Live расширения самодостаточны, поэтому не нуждаются в дергании определенной функции, чтобы работать с будущим контентом. А значит могут комбинироваться с любой существующей библиотекой для DOM и упрощают логику приложения, разделяя UI код на множество маленьких независимых частей.
В заключение несколько слов о Web components. Один и разделов спецификации, под названием «Декораторы», предназначен для решения схожей проблемы. В настоящее время он использует разметку и специальный синтаксис для навешивания слушателей на дочерние элементы. Но это пока очень ранний черновик:
Благодаря Apple в CSS сейчас есть хорошая поддержка анимаций. В прошлом анимации реализовывались на JavaScript с помощью
В better-dom нет метода
Для иллюстрации подхода давайте добавим простую анимацию тултипу, который мы написали ранее:
Внутри
Больше примеров анимаций с помощью better-dom.
HTML-строки громоздкие. Когда я начал искать замену, то нашел отличный проект Emmet. В настоящее время он достаточно популярный в качестве плагина для текстовых редакторов и имеет чистый и компактный синтаксис. Сравните:
что эквивалентно
В better-dom методы, которые принимают HTML-строки в качестве аргументов, так же поддерживают emmet-аббревиатуры. Парсер аббревиатур быстрый, поэтому можно не думать о потерях в производительности. Так же имеется функция для прекомпиляции шаблонов, которая может быть использована по мере необходимости.
Разработка UI-виджета часто требует локализацию, что не всегда простая задача. Многие решали эту проблему по-своему. С better-dom я надеюсь, что смена языка будет не сложнее изменения состояния CSS селектора.
С идеологической точки зрения переключение языка — это наподобие изменения «представления» контента. В CSS2 есть несколько псевдоселекторов, которые помогают описать такую модель:
Хитрость в том, что свойство
Разумеется, такой CSS код не выглядит привлекательным, поэтому в better-dom два хелпера:
Параметризованные строки так же поддерживаются: достаточно добавить
Обычно мы хотим придерживаться стандартов. Но иногда стандарты не совсем дружелюбные. DOM очень запутанный и, чтобы сделать его приятным, нужно обернуть его в удобный API. Несмотря на многочисленные улучшения, которые сделаны разными библиотеками, кое-какие вещи можно сделать лучше:
Нативный DOM имеет понятия атрибутов и свойств у элемента, которые могут вести себя по-разному. Предположим на странице имеется разметка:
Чтобы объяснить недружелюбие нативного DOM, давайте поработаем с ним немного:
Итак, значение атрибута равно соответствующей строке в HTML, в то время как свойство элемента с таким же именем может иметь специальное поведение, например, генерация полного URL в примере выше. Эта разница может иногда запутывать.
На практике сложно представить, когда такое разделение может быть полезным. Более того, разработчик должен все время следить за тем, с каким значением он работает, что добавляет ненужную сложность.
В better-dom дела обстоят проще: каждый элемент имеет только умный getter и setter.
На первом шаге методы делают поиск свойства элемента и, если оно определено, используют его для операций. В противном случае работают с соответствующим атрибутом. Для буленовских атрибутов (
Обработка событий — это значимая часть кодирования для DOM. Одна фундаментальная проблема, которую я обнаружил, состоит в том, что наличие event object в слушателях элемента заставляет разработчиков, которые любят тестируемый код, мОчить первый агрумент или создавать дополнительную функцию, которая принимает используемые в этом обработчике свойства события.
Это на самом деле надоедает и добавляет вызов дополнительной функции. Что если выделить меняющуюся часть в качестве аргумента: это позволит избавиться от замыкания:
По умолчанию обработчик событий принимает массив
Позднее связывание так же поддерживается (рекомендую прочитать статью от Peter Michaux по теме). Это более гибкая альтернатива обычным обработчикам событий, которая, кстати, присутствует в стандарте. Может быть полезна в случаях, когда нужно делать частые вызовы методов
В завершении стоит упомянуть что в better-dom нету методов наподобие и
ES5 стандартизировал несколько полезных методов для массивов, такие как
Каждый элемент (или коллекция) в better-dom имеет методы ниже из коробки:
Большинство проблем ниже не могут быть исправлены в jQuery без потери обратной совместимости. Еще одна причина, по которой было решено создать новую библиотеку.
Все слышали когда-нибудь, что функция
За кулисами
Несмотря на многочисленные статьи, которые продвигают кэширование объектов jQuery разработчики продолжают вставлять
Другая проблема с этой функцией состоит в том, что она является ответственной за две совершенно разные задачи. Люди уже привыкли к такому синтаксису, но это нехорошая практика дизайна функции в общем случае:
В better-dom зоны ответственности $-функции покрывают несколько методов:
Еще одна причина проблемы с слишком частыми вызовами доллар-функции — это оператор квадратных скобок. Когда создается новый jQuery-объект все связанные элементы сохраняются в numeric-свойствах. Важно заметить, что значение такого свойства содержит экземпляр нативного элемента (не jQuery-врапера):
Из-за такой особенности каждый функциональный метод в jQuery или другой библиотеки (как Underscore) требует, чтобы текущий элемент оборачивался в
В better-dom оператор квадратных скобок возвращает объект библиотеки, поэтому можно забыть о нативных элементах. Единственный легальный способ получить к ним доступ — это использовать специальный метод
Но в реальности он нужен в очень редких случаях, например, когда нужна совместимость с нативной функцией или другой DOM библиотекой (как Hammer из примера выше).
Одна вещь, которая действительно взорвала мне мозг это странная обработка
Здесь сразу несколько проблем:
Непонятно почему сообщество jQuery решило пойти против стандартов. И better-dom не собирается повторять эту ошибку:
Поиск элементов — это одна из самых дорогих операций в браузере. Две нативные функции могут использоваться чтобы реализовать его:
Эта особенность позволяет значительно уменьшить количество итераций в подходящих случаях. В моих тестах выигрыш в скорости может быть до 20 раз. Так же можно ожидать что разрыв увеличивается в зависимости от размера дерева документа.
jQuery имеет
В better-dom есть два разных метода:
Определенно, что метод
Разработка с использованием live расширений действительно упрощает жизнь на front-end. Разделение UI на множество маленьких частей помогает создавать более независимые (=надежные) решения. Но, как видно выше, better-dom не только о них (хотя это была изначальная главная цель).
Во время разработки я понял одну важную вещь: если текущие стандарты не совсем устраивают или есть идеи как можно сделать лучше — просто реализуй и докажи что они работают. И это очень весело!
Больше информации о библиотеке better-dom всегда можно найти на GitHub.
В поздние дни работы с jQuery я начал замечать разные проблемы с этой библиотекой. Большинство из них основопологающие, поэтому не могут быть исправлены без потери обратной совместимости, что, конечно, важно. Я, как и многие другие, продолжал использовать библиотеку какое-то время, встречаясь с надоедливыми причудами каждый день.
Затем Daniel Buchner создал SelectorListener, и родилась идея live расширений. Я начал подумывать о создании набора функций, который позволит создавать ненавязчивые и независимые компоненты DOM, используя лучший подход. Задача была сделать обзор существующих решений и создать более понятную, тестируемую, маленькую, но в то же время самодостаточную библиотеку.
Добавление полезных функций в библиотеку
Идея live расширений способствовала разработке проекта better-dom, хотя кроме него имеются другие интересные особенности, которые делают библиотеку уникальной. Давайте сделаем их беглый обзор:
- live расширения
- нативные анимации
- встроенный шаблонизатор
- поддержка интернационализации
Live расширения
В jQuery существует понятие live событий. За кулисами они используют event delegation чтобы обрабатывать существующие и будущие элементы. Однако во многих случаях требуется большая гибкость. Например, если виджет должен при инициализации добавить дополнительные элементы в дерево документа, которые должны взаимодействовать или замещать существующие, live события не работают. Чтобы решить проблему я представляю live расширения.
Цель — объявить расширение однажды, и после этого оно должно работать для будущего контента независимо от сложности виджета. Это важная особенность, поскольку позволяет создавать веб-страницы декларативно, поэтому хорошо подходит для AJAX приложений.
Рассмотрим простой пример. Допустим, наша задача реализовать полностью кастомизируемую всплывающую подсказку. Псевдоселектор
:hover
не подходит, потому что позиция тултипа меняется в зависимости от курсора мыши. Event delegation так же не подходит — слишком затратно слушать mouseover
и mouseleave
для всех элементов на странице. Здесь на сцену выходят live расширения.DOM.extend("[title]", {
constructor: function() {
var tooltip = DOM.create("span.custom-title");
// устанавливаем textContent всплывающей подсказки в значение
// title исходного элемента и скрываем ее изначально
tooltip.set("textContent", this.get("title")).hide();
this
// удаляем нативный tooltip
.set("title", null)
// сохраняем ссылку для более быстрого доступа
.data("tooltip", tooltip)
// регистрируем обработчики событий
.on("mouseenter", this.onMouseEnter, ["clientX", "clientY"])
.on("mouseleave", this.onMouseLeave)
// вставляем всплывающую подсказку в DOM
.append(tooltip);
},
onMouseEnter: function(x, y) {
this.data("tooltip").style({left: x, top: y}).show();
},
onMouseLeave: function() {
this.data("tooltip").hide();
}
});
Наш тултип теперь можно стилизировать с помощью селектора
.custom-title
в CSS:.custom-title {
position: fixed;
border: 1px solid #faebcc;
background: #faf8f0;
}
Однако самое интересное начинается, когда новые элементы с атрибутом
title
добавляются на страницу. Они подхватятся расширением без вызова какой-либо инициализирующей функции.Live расширения самодостаточны, поэтому не нуждаются в дергании определенной функции, чтобы работать с будущим контентом. А значит могут комбинироваться с любой существующей библиотекой для DOM и упрощают логику приложения, разделяя UI код на множество маленьких независимых частей.
В заключение несколько слов о Web components. Один и разделов спецификации, под названием «Декораторы», предназначен для решения схожей проблемы. В настоящее время он использует разметку и специальный синтаксис для навешивания слушателей на дочерние элементы. Но это пока очень ранний черновик:
Декораторы, в отличие от других разделов Web Components не имеют пока спецификации.
Нативные анимации
Благодаря Apple в CSS сейчас есть хорошая поддержка анимаций. В прошлом анимации реализовывались на JavaScript с помощью
setInterval
и setTimeout
. Это была классная фишка но теперь… что-то вроде плохой практики. Нативные анимации всегда будут более плавными: они обычно быстрее, требуют меньше энергии и просто не показываются в браузерах, которые их не поддерживают.В better-dom нет метода
animate
: только show
, hide
и toggle
. Чтобы захватить состояние скрытого элемента в CSS библиотека использует стандартизированный атрибут aria-hidden
.Для иллюстрации подхода давайте добавим простую анимацию тултипу, который мы написали ранее:
.custom-title {
position: fixed;
border: 1px solid #faebcc;
background: #faf8f0;
/* анимация */
opacity: 1;
-webkit-transition: opacity 0.5s;
transition: opacity 0.5s;
}
.custom-title[aria-hidden=true] {
opacity: 0;
}
Внутри
show
и hide
атрибут aria-hidden
меняет свое значение на false
или true
. Этого достаточно чтобы показывать анимации средствами CSS.Больше примеров анимаций с помощью better-dom.
Встроенный шаблонизатор
HTML-строки громоздкие. Когда я начал искать замену, то нашел отличный проект Emmet. В настоящее время он достаточно популярный в качестве плагина для текстовых редакторов и имеет чистый и компактный синтаксис. Сравните:
body.append("<ul><li class='list-item'></li><li class='list-item'></li><li class='list-item'></li></ul>");
что эквивалентно
body.append("ul>li.list-item*3");
В better-dom методы, которые принимают HTML-строки в качестве аргументов, так же поддерживают emmet-аббревиатуры. Парсер аббревиатур быстрый, поэтому можно не думать о потерях в производительности. Так же имеется функция для прекомпиляции шаблонов, которая может быть использована по мере необходимости.
Поддержка интернационализации
Разработка UI-виджета часто требует локализацию, что не всегда простая задача. Многие решали эту проблему по-своему. С better-dom я надеюсь, что смена языка будет не сложнее изменения состояния CSS селектора.
С идеологической точки зрения переключение языка — это наподобие изменения «представления» контента. В CSS2 есть несколько псевдоселекторов, которые помогают описать такую модель:
:lang
и :before
. Взгляните на код ниже:[data-i18n="hello"]:before {
content: "Hello Maksim!";
}
[data-i18n="hello"]:lang(ru):before {
content: "Привет Максим!";
}
Хитрость в том, что свойство
content
меняется в соответствии с текущим языком, который определяется значением атрибута lang
для элемента html
. С помощью атрибута data-i18n
мы можем использовать более общую запись:[data-i18n]:before {
content: attr(data-i18n);
}
[data-i18n="Hello Maksim!"]:lang(ru):before {
content: "Привет Максим!";
}
Разумеется, такой CSS код не выглядит привлекательным, поэтому в better-dom два хелпера:
i18n
и DOM.importStrings
. Первый используется для обновления атрибута data-i18n
с соответствующим значением, а второй локализует строки для определенного языка.label.i18n("Hello Maksim!");
// label отображает "Hello Maksim!"
DOM.importStrings("ru", "Hello Maksim!", "Привет Максим!");
// теперь если язык страницы "ru", то label будет показывать "Привет Максим!"
label.set("lang", "ru");
// теперь label показывает "Привет Максим!" независимо от языка страницы
Параметризованные строки так же поддерживаются: достаточно добавить
${param}
переменные в ключевую строку:label.i18n("Hello ${user}!", {user: "Maksim"});
// label показывает "Hello Maksim!"
Улучшение нативных API
Обычно мы хотим придерживаться стандартов. Но иногда стандарты не совсем дружелюбные. DOM очень запутанный и, чтобы сделать его приятным, нужно обернуть его в удобный API. Несмотря на многочисленные улучшения, которые сделаны разными библиотеками, кое-какие вещи можно сделать лучше:
- getter и setter
- улучшенная обработка событий
- поддержка функциональных методов
Getter и setter
Нативный DOM имеет понятия атрибутов и свойств у элемента, которые могут вести себя по-разному. Предположим на странице имеется разметка:
<a href="/chemerisuk/better-dom" id="foo" data-test="test">better-dom</a>
Чтобы объяснить недружелюбие нативного DOM, давайте поработаем с ним немного:
var link = document.getElementById("foo");
link.href; // => "https://github.com/chemerisuk/better-dom"
link.getAttribute("href"); // => "/chemerisuk/better-dom"
link["data-test"]; // => undefined
link.getAttribute("data-test"); // => "test"
link.href = "abc";
link.href; // => "https://github.com/abc"
link.getAttribute("href"); // => "abc"
Итак, значение атрибута равно соответствующей строке в HTML, в то время как свойство элемента с таким же именем может иметь специальное поведение, например, генерация полного URL в примере выше. Эта разница может иногда запутывать.
На практике сложно представить, когда такое разделение может быть полезным. Более того, разработчик должен все время следить за тем, с каким значением он работает, что добавляет ненужную сложность.
В better-dom дела обстоят проще: каждый элемент имеет только умный getter и setter.
var link = DOM.find("#foo");
link.get("href"); // => "https://github.com/chemerisuk/better-dom"
link.set("href", "abc");
link.get("href"); // => "https://github.com/abc"
link.get("data-attr"); // => "test"
На первом шаге методы делают поиск свойства элемента и, если оно определено, используют его для операций. В противном случае работают с соответствующим атрибутом. Для буленовских атрибутов (
checked
, selected
и т.д.) можно просто использовать true
или false
. Изменение этих свойств у элемента обновляет соответствующий атрибут (нативное поведение).Улучшенная обработка событий
Обработка событий — это значимая часть кодирования для DOM. Одна фундаментальная проблема, которую я обнаружил, состоит в том, что наличие event object в слушателях элемента заставляет разработчиков, которые любят тестируемый код, мОчить первый агрумент или создавать дополнительную функцию, которая принимает используемые в этом обработчике свойства события.
var button = document.getElementById("foo");
button.addEventListener("click", function(e) {
handleButtonClick(e.button);
}, false);
Это на самом деле надоедает и добавляет вызов дополнительной функции. Что если выделить меняющуюся часть в качестве аргумента: это позволит избавиться от замыкания:
var button = DOM.find("#foo");
button.on("click", handleButtonClick, ["button"]);
По умолчанию обработчик событий принимает массив
["target", "defaultPrevented"]
, поэтому нет необходимости добавлять последний аргумент, чтобы прочитать эти свойства:button.on("click", function(target, canceled) {
// обрабатываем клик
});
Позднее связывание так же поддерживается (рекомендую прочитать статью от Peter Michaux по теме). Это более гибкая альтернатива обычным обработчикам событий, которая, кстати, присутствует в стандарте. Может быть полезна в случаях, когда нужно делать частые вызовы методов
on
и off
.button._handleButtonClick = function() { alert("click!"); };
button.on("click", "_handleButtonClick");
button.fire("click"); // показывается сообщение "clicked"
button._handleButtonClick = null;
button.fire("click"); // ничего не показывается
В завершении стоит упомянуть что в better-dom нету методов наподобие и
click()
, focus()
, submit()
т.п., которые присутствуют в стандарте и имеют различное поведение в браузерах. Единственные способ их вызвать — это использовать метод fire
, который выполняет поведение по умолчанию, когда ни один из обработчиков не вернул false
:link.fire("click"); // кликает по ссылке
link.on("click", function() { return false; });
link.fire("click"); // вызывает обработчик выше но не кликает по ссылке
Поддержка функциональных методов
ES5 стандартизировал несколько полезных методов для массивов, такие как
map
, filter
, some
и т.д. Они позволяют проводить операции над коллекциями в стандартизированном виде. В результате сегодня имеются проекты наподобие Underscore или Lo-Dash, которые позволяют пользоваться этими методами в старых браузерах.Каждый элемент (или коллекция) в better-dom имеет методы ниже из коробки:
each
(отличается отforEach
тем, что возвращаетthis
вместоundefined
)some
every
map
filter
reduce[Right]
var urls, activeLi, linkText;
urls = menu.findAll("a").map(function(el) {
return el.get("href");
});
activeLi = menu.children().filter(function(el) {
return el.hasClass("active");
});
linkText = menu.children().reduce(function(memo, el) {
return memo || el.hasClass("active") && el.find("a").get()
}, false);
Решение некоторых проблем jQuery
Большинство проблем ниже не могут быть исправлены в jQuery без потери обратной совместимости. Еще одна причина, по которой было решено создать новую библиотеку.
- «магическая» функция
$
- значение оператора квадратных скобок
- проблемы с
return false
find
иfindAll
«Магическая» функция $
Все слышали когда-нибудь, что функция
$
(доллар) — это «магия». Имя, состоящее всего из одного символа, не очень понятное, функция выглядит как встроенный в язык оператор. Именно поэтому неопытные разработчики просто вызывают ее везде, где это необходимо.За кулисами
$
— это довольно сложная функция. Частое ее выполнение, особенно внутри таких событий как mousemove
или scroll
, может быть причиной плохой отзывчивости UI.Несмотря на многочисленные статьи, которые продвигают кэширование объектов jQuery разработчики продолжают вставлять
$
. Это потому, что синтаксис библиотеки способствует такому стилю кодирования.Другая проблема с этой функцией состоит в том, что она является ответственной за две совершенно разные задачи. Люди уже привыкли к такому синтаксису, но это нехорошая практика дизайна функции в общем случае:
$("a"); // => поиск всех элементов, которые соответствуют селектору “a”
$("<a>"); // => создает элемент <a> с jQuery врапером
В better-dom зоны ответственности $-функции покрывают несколько методов:
find[All]
и DOM.create
. Методы find[All]
используются для поиска элементов по CSS-селектору. DOM.create
создает новые элементы в памяти. Имена функций ясно говорят что эти функции делают.Значение оператора квадратных скобок
Еще одна причина проблемы с слишком частыми вызовами доллар-функции — это оператор квадратных скобок. Когда создается новый jQuery-объект все связанные элементы сохраняются в numeric-свойствах. Важно заметить, что значение такого свойства содержит экземпляр нативного элемента (не jQuery-врапера):
var links = $("a");
links[0].on("click", function() { ... }); // ошибка!
$(links[0]).on("click", function() { ... }); // теперь все хорошо
Из-за такой особенности каждый функциональный метод в jQuery или другой библиотеки (как Underscore) требует, чтобы текущий элемент оборачивался в
$()
внутри итерационной функции. Поэтому разработчик обязан всегда помнить с каким объектом он работает: нативным или врапером, несмотря на факт, что используется библиотека для работы с DOM.В better-dom оператор квадратных скобок возвращает объект библиотеки, поэтому можно забыть о нативных элементах. Единственный легальный способ получить к ним доступ — это использовать специальный метод
legacy
.var foo = DOM.find("#foo");
foo.legacy(function(node) {
// используя библиотеку Hammer слушаем жест swipe
Hammer(node).on("swipe", function(e) {
// обрабатываем жест swipe
});
});
Но в реальности он нужен в очень редких случаях, например, когда нужна совместимость с нативной функцией или другой DOM библиотекой (как Hammer из примера выше).
Проблемы с return false
Одна вещь, которая действительно взорвала мне мозг это странная обработка
return false
в слушателях событий. В соответствии с стандартами W3C это значение должно в большинстве случаев отменять поведение по умолчанию. В jQuery return false
дополнительно останавливает event delegation!Здесь сразу несколько проблем:
- вызов
stopPropagation()
сам по себе может создавать проблемы с совместимостью, т.к. он ломает возможность других слушателей делать их работу по возникновению такого события - большинство разработчиков (даже опытных) не ожидают такого поведения
Непонятно почему сообщество jQuery решило пойти против стандартов. И better-dom не собирается повторять эту ошибку:
return false
внутри обработчика событий вызывает только preventDefault()
, как и ожидается.find и findAll
Поиск элементов — это одна из самых дорогих операций в браузере. Две нативные функции могут использоваться чтобы реализовать его:
querySelector
и querySelectorAll
. Разница между ними в том, что первая останавливает поиск после первого совпадения.Эта особенность позволяет значительно уменьшить количество итераций в подходящих случаях. В моих тестах выигрыш в скорости может быть до 20 раз. Так же можно ожидать что разрыв увеличивается в зависимости от размера дерева документа.
jQuery имеет
find
метод, который использует querySelectorAll
в общем случае. На сегодняшний день здесь нет метода, который бы использовал querySelector
, чтобы найти только первый подходящий элемент.В better-dom есть два разных метода:
find
и findAll
. Они позволяют использовать querySelector
-оптимизацию выше. Чтобы оценить потенциальный выигрыш, я сделал выборку по количеству вхождений в исходном коде последнего коммерческого проекта:find
— 103 совпадений в 11 файлахfindAll
— 14 совпадений в 4 файлах
Определенно, что метод
find
горазде более популярный. Это значит, что querySelector
-оптимизация имеет место в большинстве случаев, поэтому может дать ощутимый выигрыш в производительности кода на клиенте.Заключение
Разработка с использованием live расширений действительно упрощает жизнь на front-end. Разделение UI на множество маленьких частей помогает создавать более независимые (=надежные) решения. Но, как видно выше, better-dom не только о них (хотя это была изначальная главная цель).
Во время разработки я понял одну важную вещь: если текущие стандарты не совсем устраивают или есть идеи как можно сделать лучше — просто реализуй и докажи что они работают. И это очень весело!
Больше информации о библиотеке better-dom всегда можно найти на GitHub.