Как и в Vue, директивы атрибутов в TLX могут принимать аргументы с разделителями «:». В этой статье показано, как создать собственные директивы настраиваемых атрибутов, которые принимают аргументы, путем реализации директивы at-bind, которая делает то же самое, что и v-bind.

Помимо возможностей Vue, статья также иллюстрирует, как сами аргументы директивы атрибута могут быть динамическими, то есть вы можете сделать что-то вроде этого: <div t-bind:${attributeName}="${value}">...</div>. И даже это, <div ${directiveName}:${argument}="${value}">...</div>.

Прежде чем продолжить чтение этой статьи, вы можете прочитать Директивы пользовательских атрибутов в TLX.

Директива v-bind в Vue просто берет имя атрибута и устанавливает его значение равным значению директивы, например.

<a v-bind:href="url">My Server</a>

предполагая, что url = “http://localhost"будет отображаться как

<a href="http://localhost">My Server</a>

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

Подпись для функций определения директив атрибутов в tlx:

(resolvedAttributeValue,model,actions,renderFunction,directiveData)

directiveData — это объект с тремя свойствами: raw, resolved и element. Свойство raw — это строка, представляющая имя директивы. Свойство resolved обычно представляет собой ту же строку, за исключением того, что сами имена директив могут содержать строки шаблонов, а в этом свойстве эти строки шаблонов разрешены (подробнее об этом позже). element — это обрабатываемый узел DOM.

Ниже приведена пользовательская функция директивы, которая анализирует директиву и соответствующим образом устанавливает атрибут.

tlx.directives["t-bind"] =
  (value,model,actions,render,{resolved,element}={}) => {
    // resolved has the form t-bind:attributeName
    const [_,attributeName] = resolved.split(":");
    element.setAttribute(attributeName,value);
    return true;
  }

Обратите внимание, что t-bind не обрабатывает элемент, он просто возвращает true. Это связано с тем, что он может полагаться на обычный рендеринг браузера для отображения элемента, учитывая, что он просто установил значение атрибута и, в отличие от чего-то вроде t-for, не делает ничего особенного с вложенным содержимым.

Тогда tlx-эквивалент Vue будет выглядеть следующим образом:

<a t-bind:href="${url}">My Server</a>

Вы можете найти работающий пример на JSFiddle.

Учитывая, что реализация t-bind такая короткая и простая, вы можете удивиться, почему ее нет в tlx по умолчанию. Есть две причины:

  1. Это позволяет максимально уменьшить размер ядра tlx.
  2. В этом нет необходимости, так как вы можете просто привязать значения непосредственно к атрибутам, например. ‹a href="${url}›Мой сервер‹/a›

Как упоминалось во введении, tlx также поддерживает динамические аргументы для директив атрибутов. Итак, если по какой-то причине вы определяете во время выполнения, какой атрибут привязать, вы можете сделать это:

<div t-bind:${attributeName}="${attributeValue}">

Если мы возьмем модель, которая выглядит так:

{attributeName:”checked",attributeValue:true}

Затем во время выполнения значение четвертого аргумента функции определения директивы будет иметь следующее содержимое:

{
  element: {...},
  raw: 't-bind:${attributeName}',
  resolved: 't-bind:checked'
}

Для справки и немного более сложного примера, вот внутреннее определение t-for:

"t-for": (value,scope,actions,render,{raw,resolved,element}={}) => {
  // directive is of the form "t-for:varname:looptype"
  const [_,vname,looptype] = resolved.split(":");
  if(looptype==="in") {
    for(let key in value) {
      render(Object.assign({},scope,{[vname]:key}))
    }
  } else if(looptype==="of") {
    for(let item of value) {
      render(Object.assign({},scope,{[vname]:item}))
    }
  } else {
   throw 
   new TypeError(`loop type must be 'in' or 'of' for ${raw}`);
  }
  return element;
}

Вы можете найти tlx на GitHub.