Riot.js является современным и минималистичным фреймворком для разработки пользовательских интерфейсов на JavaScript, который использует компонентный подход. Основной строительный блок приложения в Riot — пользовательский тег (custom tag), объединяющий разметку, логику и стиль в одном модуле.
Пользовательский тег в Riot.js создаётся с помощью функции
riot.define или, в новых версиях, с использованием
синтаксиса <tag> в отдельном файле .tag.
Основная структура включает три ключевых секции:
Разметка (markup) Содержит HTML-шаблон компонента. В шаблоне могут использоваться специальные синтаксические конструкции Riot:
{ expression } — для вывода данныхeach={items} — для перебора массивовif={condition} — для условного рендерингаЛогика (script) Внутри тега можно определять методы, вычисляемые свойства, слушатели событий и жизненный цикл компонента:
this.on('mount', () => {
console.log('Компонент смонтирован');
});
this.increment = () => this.count++;Стили (style) Каждый тег может содержать scoped CSS, который применяется только к этому компоненту:
<style>
.counter {
font-size: 20px;
color: blue;
}
</style>Пример простого компонента счётчика:
<counter>
<p class="counter">{ count }</p>
<button oncl ick={ increment }>Увеличить</button>
<script>
this.count = 0
this.increment = () => this.count++
</script>
<style>
.counter {
font-weight: bold;
margin-bottom: 10px;
}
</style>
</counter>
this.count — локальное состояние компонента.oncl ick={ increment } — связывает событие кнопки с
методом компонента..counter не повлияют
на другие элементы страницы.Riot.js предоставляет набор хуков, позволяющих управлять состоянием компонента на разных этапах его существования:
this.on('mount', callback) — вызывается после
добавления компонента в DOM.this.on('update', callback) — срабатывает при
обновлении состояния.this.on('unmount', callback) — выполняется перед
удалением компонента из DOM.Пример использования:
this.on('mount', () => {
console.log('Компонент смонтирован');
});
this.on('update', () => {
console.log('Компонент обновлён');
});
this.on('unmount', () => {
console.log('Компонент удалён');
});
Теги могут принимать входные данные через props, которые задаются при использовании компонента:
<counter initial={5}></counter>
<script>
this.count = this.props.initial || 0
</script>
this.props содержит все переданные атрибуты.this.update().Один тег может содержать другие пользовательские теги, что обеспечивает модульность и переиспользуемость компонентов:
<app>
<counter initial={10}></counter>
<counter initial={20}></counter>
</app>
Каждый counter работает независимо, сохраняя собственное
состояние.
Для обмена данными между тегами используется система событий:
this.trigger('countChanged', this.count)
Родительский компонент может слушать события дочернего:
<counter oncountChan ged={handleChange}></counter>
<script>
handleChange = (value) => {
console.log('Новое значение:', value)
}
</script>
Riot.js поддерживает вложенные стили и наследование через классы. Можно определять общие CSS-классы для нескольких тегов, комбинируя их с scoped стилями:
<counter>
<style>
:host {
display: block;
margin: 5px;
}
.counter {
color: green;
}
</style>
</counter>
:host применяется к корневому элементу тега, облегчая
стилизацию контейнера.
Пользовательские теги в Riot.js обеспечивают чёткое разделение логики, разметки и стилей, поддержку локального состояния, событий и модульность компонентов. Они позволяют создавать повторно используемые элементы интерфейса, управлять их жизненным циклом и интегрировать с родительскими компонентами через props и события. Такой подход делает разработку интерфейсов более организованной и удобной для масштабирования.