Как и в 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 по умолчанию. Есть две причины:
- Это позволяет максимально уменьшить размер ядра tlx.
- В этом нет необходимости, так как вы можете просто привязать значения непосредственно к атрибутам, например. ‹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.