Skip to content

Latest commit

 

History

History
254 lines (160 loc) · 14.2 KB

b-define.md

File metadata and controls

254 lines (160 loc) · 14.2 KB

<b:define>

Инструкция используется для определения возможных значений биндинга в атрибуте 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 (опциональный) – значение по умолчанию

Другие атрибуты зависят от заданного типа.

name

Задает имя определения. Это имя должно быть валидным идентификатором и используется в качестве имени биндинга в разметке, но только для атрибута class. По сути инструкция переопределяет биндинг для атрибута class.

В случае отсутствия атрибута from, значение атрибута так же является именем биндинга, чье значение тестируется. Если определение имеет тип bool или invert, то имя используется в качестве имени класса.

from

Атрибут позволяет задать имя биндинга, в случае если имя определения и биндинга не совпадают. В качестве значения используются только оригинальные биндинги передаваемые в шаблон. Определения объявленные с помощью <b:define> не учитываются.

Один из способ использования – переименование биндинга:

<b:define name="active" from="selected" type="bool"/>

<div class="{active}"/>

В данном примере, если selected == true у <div> будет класс active, иначе класса не будет.

type

Атрибут определяет тип значения и может принимать следующие значения:

  • bool – приведение значения к boolean
  • invert – инверсия значения
  • enum – фиксированный список значений

bool

Данный тип задает приведение значения биндинга к 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>

invert

Противоположность типу 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>

enum

Позволяет задать фиксированный список допустимых значений. Вставляет класс в том случае, если значение биндига входит в заданный список.

Список значений задается атрибутом 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>

default

Трактовка значения атрибута зависит от заданного типа.

Указание значения по умолчанию дает возможноть определить какие классы будут расставлены в разметке изначально, до применения значений биндингов. Это полезно для ситуаций, когда значение биндинга может не передаваться в шаблон.

Так же атрибут позволяет оптимизировать создание шаблона. Если известно, что некоторый биндинг при создании чаще всего имеет определенное значение, можно изначально проставить класс с этим значением, там самым избежать операции уставки этого класса отдельной операцией при создании экземпляра шаблона.

Например, практически все экземпляры 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> – удаление указанные биндинги без учета того какие ограничения к ним применяются