В статьях Замена JSX шаблонными литералами и Легкое создание HTML-шаблонов с помощью TLX мы представили TLX, интерфейсную библиотеку, которая объединяет ключевые функции React и Vue в одну небольшую библиотеку. В этой статье мы расскажем о директивах атрибутов, поддерживаемых TLX, а также о том, как добавить собственные директивы всего в одну строчку кода!

TLX поддерживает следующие встроенные директивы:

  1. state который, как вы уже догадались, устанавливает состояние данных элементов.
  2. t-for=<vname> of <array>, который работает как его аналог JavaScript.
  3. t-for=<vname> in <object>, который работает как его аналог JavaScript.
  4. t-foreach=<object>, который работает как его аналог массива JavaScript, а также обрабатывает объекты.
  5. t-if=<expression>,, который будет отображать вложенный HTML только в том случае, если <expression> является правдой.
  6. t-on={<eventName>:<function>[,...]}>, который прикрепляет обработчики событий к элементам.

Все встроенные директивы реализуются точно так же, как и пользовательские директивы, подробнее об этом позже.

Состояние

Атрибут state="${{name:'Joe',age:27}}", сделает переменные name и age доступными для шаблонов, используемых в любом HTML, вложенном внутри элемента, объявляющего атрибут, например

<div state="${{name:'Joe',age:27}}">
  Name: ${name}<br>
  Age: ${age}
</div>

будет отображаться как:

Имя: Джо
Возраст: 27

Независимо от порядка атрибутов, атрибут state обрабатывается перед любыми другими директивами.

Кроме того, и это относится ко всем директивам, переменная может быть скрыта дополнительным вложенным HTML, например

<div state="${{name:'Joe',age:27}}">
  Name: ${name}<br>
  Age: ${age}
  <div state="${{name:'Mary'}}">
    Name: ${name}
  </div>
</div>

будет отображаться как:

Имя: Джо
Возраст: 27
Имя: Мэри

Итерации

Итерации работают немного иначе, чем Vue. Выражение итерации помещается в содержащий элемент. Этот параллельный регулярный код не только немного более точен, но и упрощает внутреннюю структуру TLX.

<ul t-for="item of ${[1,2,3]}">
  <li>${item}</li>
</ul>

будет отображаться как:

  • 1
  • 2
  • 3

Для удобства также доступны переменные value, index и array, как если бы был вызван [1,2,3].forEach((value,index,array)=>...).

Аналогичным образом HTML

<div t-for="property in ${{name:'Joe',age:27}}">
  <div>${property}: ${object[property]}</div>
</div>

отобразит:

имя: Джо
возраст: 27

И для удобства доступны переменные key и object. Следовательно, следующий результат даст тот же результат:

<div t-for="property in ${{name:'Joe',age:27}}">
  <div>${property}: ${object[key]}</div>
</div>

Vue не имеет директивы foreach, которая может принимать массив или объект, TLX:

<div t-foreach="${{name:'Joe',age:27}}">
  <div>${key}: ${value}</div>
</div>

и

<div t-foreach="${[1,2,3]}">
  <div>${key}: ${value}</div>
</div>

можно использовать оба.

Условные

Условное выражение t-if предотвратит рендеринг любого вложенного HTML, если значение его выражения является ложным; следовательно,

<div t-if="${age>27}" state="${{name:'Joe',age:27}}">
  <div t-for="property in ${state}">
  <div>${property}: ${object[property]}</div>
</div>

ничего не будет отображать, поскольку атрибут state обрабатывается первым и age не превышает 27. Также обратите внимание, что сам state доступен как переменная в пределах области элемента.

Обработчики событий

Директива t-on поддерживает добавление нескольких обработчиков событий с одним значением, объектом, ключи которого являются именами событий, а значения - функциями, например:

<input type="text" t-on="${{focus: (event) => console.log(event),click: (event) => console.log(event)}}">

будет регистрировать все события фокуса и щелчка на консоли.

Пользовательские директивы

Всего в этих 6 директивах много силы, но что, если вам нужно больше? Вы можете создать их всего одной линией!

Директива атрибута t-if в файле tls-directives.js реализована настолько просто, насколько это возможно:

"t-if": (value,vnode) => { if(!value) { vnode.children = null; } }

Вот немного более сложный пример, добавленный в код пользователя, а не в tlx-directives.js:

tlx.directives.VNode["t-capitalize"] = (_,vnode) => vnode.children.forEach((child,i) => child instanceof tlx.VNode || (vnode.children[i] = new tlx.VText({text:child.text.toUpperCase(),parent:child.parent}))))

Этот код принимает VNode и использует заглавные буквы всех дочерних элементов, которые являются строками, то есть узлами VText, до их рендеринга, независимо от значения, связанного с атрибутом, т.е. он работает как унарные атрибуты hidden и selected.

Пользовательские директивы назначаются tlx.directives.VNode, и все они принимают значение директивы и виртуальное представление узла DOM, с которым связана директива, в качестве аргументов.

VNode имеет следующие свойства:

  • nodeName, что похоже на tagName, но в нижнем регистре.
  • attributes, который является объектом, ключи которого представляют собой имена атрибутов со значениями, которые могут быть aboolean, number, string или object..
  • children, который представляет собой массив дочерних узлов VNode или VText.

Сданный vnode может быть изменен любым желаемым образом.

В следующей статье мы рассмотрим настраиваемые теги и компоненты и представим мощный универсальный редактор, который инкапсулирует input, select-one, select-multiple иtextarea, добавляя возможности radiogroupи звездочки rating.