Одним из преимуществ строковых шаблонизаторов таких как JUST.js, jqueryTmpl или handlebarsjs перед шаблонизаторами на основе виртуального DOM дерева (VUE.js, angular) это низкий порог вхождения и простота в использовании. Ещё как мне кажется со строковыми шаблонизаторами проще интегрировать плагины для jquery.
Однако возможность реактивного связывания данных модели с шаблоном действительно удобный инструмент, и после того как я пробовал VUE.js и angular мне стало очень не хватать этого в моём любимом шаблонизаторе JUST.JS.
В итоге я решил добавить одностороннее реактивное связывание данных в JUST.JS, а в итоге получилось решение которое можно использовать практически с любым строковым шаблонизатором.
В нём мы обошлись вообще без шаблонизатора для простоты и наглядности кода. В данном примере раз в секунду в переменную присваивается новое значение. И затем justReactive за вас вносит измения в dom дерево страницы.
Библиотека justReactive добавляет следующие методы для Object каждый из которых предназначен для вставки отслеживаемого значения в разные места html кода.
Следующий вызов:
вернёт вам html код который надо вставить в шаблон на то место где должна быть ваша переменная. Он избыточный, то есть помимо значения самой переменной нам приходится её оборачивать дополнительными элементами.
Так на пример justText вернёт следующий html-код:
Такая избыточность порой мешает при вёрстке, но эта та цена которая необходима для возможности в дальнейшем менять значение прямо на странице. Путём выполнения простого присваивания.
Так же надо учитывать то что после добавления отслеживания переменной её значение подменяется на объект с гетером и сетером (для тех кто не знает про такую возможность) и в дальнейшем при присваиваниях они вызываются, так что если вы уже используете функции гетеров и сетеров в своём коде то надо подумать над отсутствием конфликтов.
Этот пример основан на предыдущем. Здесь мы добавили отслеживание ещё переменной model.class для изменения класса элемента и переменной model.hide для скрытия ещё одного элемента.
У такого подхода есть ряд проблем которые нужно учитывать при работе с кодом. В следующей ситуации мы можем получить не то что хотели:
В данном примере значение в dom дереве не будет обновлено так как присваивание в model = {key1:2}; фактически сначала удалило отслеживаемый нами model.key1, а потом создало новый объект model с таким же, но не тем же самым ключом key1.
Для изменения отдельных элементов того что мы рассмотрели достаточно. Но для работы иногда хочется при изменении одной переменной перестроить целый блок шаблона. На пример если мы отслеживаем массив и в него добавился ещё один элемент хочется перестроить весь список элементов.
Для решения этой задачи мы бы могли вставлять сразу большой блок html кода в какой то из элементов.
Но такое хоть и работает но всё же не очень удобно. Я лично для себя сделал форк шаблонизатора just.js и добавил в него ряд дополнительных возможностей попутно вырезав то что мне казалось в нём лишнем.
Получившийся модифицированый шаблонизатор я назвал just-template
В него я добавил конструкцию для отслеживания переменных модели которая сразу перестраивает вложенный в неё блок шаблона. При этом через замыкание доступны все переменные переданные при построении шаблона в первый раз.
Добавил фильтрацию данных:
И полностью выпилил всю асинхронность так как я это использую только на фронтенде и отсутствие асинхронности сильно упрощает код. И даёт без проблем собирать финальную страницу по кусочкам вызовами нескольких разных шаблонов.
Финальный пример с массивом и циклами и шаблоном.
Однако возможность реактивного связывания данных модели с шаблоном действительно удобный инструмент, и после того как я пробовал VUE.js и angular мне стало очень не хватать этого в моём любимом шаблонизаторе JUST.JS.
В итоге я решил добавить одностороннее реактивное связывание данных в JUST.JS, а в итоге получилось решение которое можно использовать практически с любым строковым шаблонизатором.
Начнём с простого примера
В нём мы обошлись вообще без шаблонизатора для простоты и наглядности кода. В данном примере раз в секунду в переменную присваивается новое значение. И затем justReactive за вас вносит измения в dom дерево страницы.
Библиотека justReactive добавляет следующие методы для Object каждый из которых предназначен для вставки отслеживаемого значения в разные места html кода.
- justHtml — отображение текста или html кода из переменной без какой либо фильтрации
- justText — отображение текста из переменной как текста, с преобразованием html сущностей в текст
- justClass — подставляет класс если значение отслеживаемой переменой не false
- justNotClass — подставляет класс если значение отслеживаемой переменой false
- justClassName — подставляет как класс само значение отслеживаемой переменой
- justAttr — подставляет и обновляет атрибут у элемента
Принцип действия
Следующий вызов:
model.justText('time')
вернёт вам html код который надо вставить в шаблон на то место где должна быть ваша переменная. Он избыточный, то есть помимо значения самой переменной нам приходится её оборачивать дополнительными элементами.
Так на пример justText вернёт следующий html-код:
<div id="_justReactive2" style="display: inline;" class="just-watch just-watch-text">1498115282970</div>
Такая избыточность порой мешает при вёрстке, но эта та цена которая необходима для возможности в дальнейшем менять значение прямо на странице. Путём выполнения простого присваивания.
Так же надо учитывать то что после добавления отслеживания переменной её значение подменяется на объект с гетером и сетером (для тех кто не знает про такую возможность) и в дальнейшем при присваиваниях они вызываются, так что если вы уже используете функции гетеров и сетеров в своём коде то надо подумать над отсутствием конфликтов.
Ещё пример использования
Этот пример основан на предыдущем. Здесь мы добавили отслеживание ещё переменной model.class для изменения класса элемента и переменной model.hide для скрытия ещё одного элемента.
Недостатки подхода
У такого подхода есть ряд проблем которые нужно учитывать при работе с кодом. В следующей ситуации мы можем получить не то что хотели:
var model = {};
model.key1 = 1;
$("#time1").html(model.justText('key1'))
model = {key1:2};
В данном примере значение в dom дереве не будет обновлено так как присваивание в model = {key1:2}; фактически сначала удалило отслеживаемый нами model.key1, а потом создало новый объект model с таким же, но не тем же самым ключом key1.
Циклы и блоки шаблонов
Для изменения отдельных элементов того что мы рассмотрели достаточно. Но для работы иногда хочется при изменении одной переменной перестроить целый блок шаблона. На пример если мы отслеживаем массив и в него добавился ещё один элемент хочется перестроить весь список элементов.
Для решения этой задачи мы бы могли вставлять сразу большой блок html кода в какой то из элементов.
Но такое хоть и работает но всё же не очень удобно. Я лично для себя сделал форк шаблонизатора just.js и добавил в него ряд дополнительных возможностей попутно вырезав то что мне казалось в нём лишнем.
Получившийся модифицированый шаблонизатор я назвал just-template
В него я добавил конструкцию для отслеживания переменных модели которая сразу перестраивает вложенный в неё блок шаблона. При этом через замыкание доступны все переменные переданные при построении шаблона в первый раз.
<~ this.data.itemslist>
<% for(var i in this.data.itemslist){ %>
<li><%= this.data.itemslist[i].justText('name') %> - <%- this.data.itemslist[i].text %></li>
<% } %>
<~>
Добавил фильтрацию данных:
<%- text %> - с фильтрацией
<%= text %> - без фильтрации
И полностью выпилил всю асинхронность так как я это использую только на фронтенде и отсутствие асинхронности сильно упрощает код. И даёт без проблем собирать финальную страницу по кусочкам вызовами нескольких разных шаблонов.
Финальный пример с массивом и циклами и шаблоном.
Ссылки
Поделиться с друзьями
Rastishka
Вы утверждаете что ваш кошмар проще vue и ниже порог вхождения?
Вы vue вообще смотрели, чтобы сравнивать?
Levhav
А вы статью читали? Я не сравнивал своё решение с vue или angular я показал как можно сделать одностороннее связывание данных модели и шаблона для строковых шаблонизаторов подобно тому как оно работает в vue.
Fragster
т.е. если это преимущество, то порог ниже, а использование — проще