Инструкция используется для определения возможных значений биндинга в атрибуте class
.
По умолчанию для биндингов в атрибуте class
простые правила, которые могут приводить к непредсказуемому результату и не всегда безопасны. Например:
<div class="{example}"/>
В этом случае, если значение биндинга {example}
является true
, то будет использоваться example
в качестве имени класса, а для, например, значения foo
имя класса будет foo
. Инструкция <b:define>
позволяет зафиксировать тип значения и определить конечный список используемых значений.
В следующем примере для example
задан тип bool
. Это значит, что независимо от значение биндинга example
оно будет приводиться к boolean
. Таким образом гарантируется что у <div>
либо будет класс example
, либо ни одного класса.
<b:define name="example" type="bool"/>
<div class="{example}"/>
Знание о возможных значениях биндинга в атрибуте class
позволяет:
-
получать предсказуемые имена классов
-
находить соответствия между имена классов в шаблонах и стилях, для обнаружения неиспользуемого CSS и классов в шаблонах, для которых нет стилей
Этим занимается инструмент
basisjs-tools
(а точнее его частьbasisjs-tools-build
). Эту информацию можно получить в консоли командойbasis lint
или в плагине. -
безопасно минизировать имена классов в сборке
Если все имена определены, сборщику можно указать флаг
--css-optimize-names
, и тогда он минимизирует имена классов в шаблонах иCSS
(до одно-/двух-буквенных), тем самым уменьшая размер сборки. -
обнаруживать конфликты, когда одинаковые имена классов могут быть образованы разными биндингами, что может привести к ошибкам;
На данных момент такая проверка не делается, но она должна быть добавлена.
Основные атрибуты:
name
– имя значения, для которого описывается правилоfrom
(опционально) – имя биндинга, который является источником значенияtype
– тип получаемого значенияdefault
(опциональный) – значение по умолчанию
Другие атрибуты зависят от заданного типа.
Задает имя определения. Это имя должно быть валидным идентификатором и используется в качестве имени биндинга в разметке, но только для атрибута class
. По сути инструкция переопределяет биндинг для атрибута class
.
В случае отсутствия атрибута from
, значение атрибута так же является именем биндинга, чье значение тестируется. Если определение имеет тип bool
или invert
, то имя используется в качестве имени класса.
Атрибут позволяет задать имя биндинга, в случае если имя определения и биндинга не совпадают. В качестве значения используются только оригинальные биндинги передаваемые в шаблон. Определения объявленные с помощью <b:define>
не учитываются.
Один из способ использования – переименование биндинга:
<b:define name="active" from="selected" type="bool"/>
<div class="{active}"/>
В данном примере, если selected == true
у <div>
будет класс active
, иначе класса не будет.
Атрибут определяет тип значения и может принимать следующие значения:
bool
– приведение значения кboolean
invert
– инверсия значенияenum
– фиксированный список значений
Данный тип задает приведение значения биндинга к boolean
. Если значение тождественно true
, то вставляется имя класса, которое соотвествует значению атрибута name
. В противном случае класс не вставляется.
Если значение атрибута default
равно true
, то значение по умолчанию true
. Для любого другого значениях или если атрибут не указан, то значение по умолчанию – false
.
<b:define name="foo" type="bool"/>
<div class="example {foo} prefix_{foo}"/>
Без установки значения биндингу:
<div class="example"></div>
foo == true
:
<div class="example foo prefix_foo"></div>
foo != true
:
<div class="example"></div>
Противоположность типу bool
. Исходное значение приводится к boolean
и инвертируется. Имя класса, которое соотвествует значению атрибута name
, вставляется в случае, если исходное значение тождественно false
. В противном случае класс не вставляется.
Значение атрибута default
определяет исходное значение для биндинга источника, которое инвертируется. Таким образом, если для атрибута задано значение true
или атрибут опущен, то значением true
. Для любого другого значениях или если атрибут не указан, то значение по умолчанию – false
.
<b:define name="foo" type="invert"/>
<div class="example {foo} prefix_{foo}"/>
Без установки значения биндингу:
<div class="example foo prefix_foo"></div>
foo == true
:
<div class="example"></div>
foo != true
:
<div class="example foo prefix_foo"></div>
Позволяет задать фиксированный список допустимых значений. Вставляет класс в том случае, если значение биндига входит в заданный список.
Список значений задается атрибутом values
, значения разделяются пробелом. Значения сравнивается оператором ==
, поэтому в списке возможно задать числовые значения.
Значение атрибута default
используется только в том случае, если такое значение определено в списке значений. В противном случае, или если атрибут не указан, по умолчанию класс вставлен не будет.
<b:define name="state" type="enum" values="processing ready error"/>
<b:define name="notReady" from="state" type="enum" values="processing"/>
<div class="prefix_{state} example_{notReady}"/>
Для state
будут приниматься только три значения и образовываться классы item_processing
, item_ready
и item_error
– при других значениях класс добавлен не будет. Для notReady
класс example_processing
будет вставлен только если state
(оригинальный биндинг) равен processing
Без установки значения биндингу:
<div></div>
state == 'ready'
:
<div class="prefix_ready"></div>
state == 'processing'
:
<div class="prefix_processing example_processing"></div>
Трактовка значения атрибута зависит от заданного типа.
Указание значения по умолчанию дает возможноть определить какие классы будут расставлены в разметке изначально, до применения значений биндингов. Это полезно для ситуаций, когда значение биндинга может не передаваться в шаблон.
Так же атрибут позволяет оптимизировать создание шаблона. Если известно, что некоторый биндинг при создании чаще всего имеет определенное значение, можно изначально проставить класс с этим значением, там самым избежать операции уставки этого класса отдельной операцией при создании экземпляра шаблона.
Например, практически все экземпляры basis.ui.Node
создаются с selected: false
и unselected: true
соотвественно. Если в шаблоне используются оба значения, то выгоднее описать шаблон так:
<b:define name="selected" type="bool"/>
<b:define name="unselected" type="bool" default="true"/>
<div class="item item_{selected} item_{unselected}"/>
Тогда эталонный DOM
фрагмент, который клонируется при создании экземпляра шаблона, будет таким:
<div class="item item_unselected"/>
И при создании экземпляра шаблона никаких изменений в полученном DOM
фрагменте будет не нужно. Без заданного default="true"
у unselected
, каждому DOM
-фрагменту будет добавлен класс item_unselected
отдельной операцией.
Оптимизация с использованием
default
имеет смысл только для шаблонов, которые создаются в большом количестве в один момент времени. В противном случае она не оказывает значимого влияния.
Определения <b:define>
действуют в рамках описания шаблона и не распространяются на включаемые шаблоны:
<b:define name="foo" type="bool"/>
<div class="{foo}">
<b:include src="./button.tmpl"/>
</div>
button.tmpl
<b:define name="foo" type="enum"/>
<button class="{foo}">
OK
</button>
Результирующая разметка (foo = 'scopes'
):
<div class="foo">
<button class="scopes">
OK
</button>
</div>
Как видно из примера, один и тот же биндинг имеет разные определения в разных шаблонах и они не пересекаются.
<b:define>
влияет только на инструкции <b:include>
, которые работают с атрибутом class
:
<b:set-class>
– задает биндинги с определениями из той области видимости, где определена сама инструкция<b:class>
и<b:append-class>
– добавляет биндинги с определениями из той области видимости, где определена сама инструкция; если у атрибутаclass
уже есть похожий биндинг, то он замещается<b:remove-class>
– удаление указанные биндинги без учета того какие ограничения к ним применяются