Вложенные компоненты и композиция

Riot.js обеспечивает лёгкую и удобную систему для создания интерфейсов через компоненты, позволяя строить сложные приложения из небольших, повторно используемых модулей. Важным аспектом разработки на Riot.js является работа с вложенными компонентами и композицией, что позволяет управлять структурой приложения и повышать его масштабируемость.


Создание вложенных компонентов

В Riot.js компонент представляет собой комбинацию HTML-шаблона, CSS-стилей и JavaScript-кода. Вложенные компоненты создаются путем включения одного компонента внутрь другого через тег с именем компонента.

// components/button.riot
<my-button>
  <button oncl ick={handleClick}>{props.label}</button>

  <script>
    export default {
      handleClick() {
        console.log('Кликнуто:', this.props.label)
      }
    }
  </script>
</my-button>
// components/app.riot
<app>
  <my-button label="Сохранить"></my-button>
  <my-button label="Отменить"></my-button>
</app>

Ключевые моменты:

  • props используются для передачи данных от родительского компонента к дочернему.
  • Вложенные компоненты рендерятся автоматически при монтировании родителя.
  • Любые изменения props в родителе могут инициировать обновление дочернего компонента через реактивную систему Riot.js.

Передача данных в дочерние компоненты

Передача данных в дочерние компоненты осуществляется через свойства (props). Это позволяет создавать динамические компоненты, которые изменяют своё поведение в зависимости от переданных данных.

<user-card name="Иван" age={30}></user-card>

<script>
  export default {
    props: {
      name: String,
      age: Number
    }
  }
</script>

Riot.js автоматически связывает значения атрибутов с полями props. Это облегчает работу с данными и делает компоненты более универсальными.


Вложенные компоненты с событиями

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

<child-component oncl ick={notifyParent}></child-component>

<script>
  export default {
    notifyParent() {
      this.$emit('custom-event', { message: 'Данные от дочернего' })
    }
  }
</script>

Родительский компонент может подписываться на эти события через атрибуты:

<child-component oncustom-event={handleEvent}></child-component>

<script>
  export default {
    handleEvent(event) {
      console.log(event.detail.message)
    }
  }
</script>

Особенности:

  • this.$emit создаёт событие с именем и данными.
  • Атрибут onимя-события в родителе связывает обработчик с событием.
  • Такой подход реализует коммуникацию “снизу вверх”, сохраняя компонентность.

Композиция компонентов

Riot.js поддерживает композицию, позволяя строить сложные интерфейсы из комбинации базовых компонентов. Композиция может быть вертикальной (родитель → дети) и горизонтальной (соседние компоненты на одном уровне).

<dashboard>
  <header-bar title="Главная"></header-bar>
  <sidebar-menu></sidebar-menu>
  <main-content>
    <user-card name="Анна" age={25}></user-card>
    <user-card name="Пётр" age={28}></user-card>
  </main-content>
</dashboard>

Преимущества композиции:

  • Повторное использование компонентов в разных частях приложения.
  • Разделение ответственности (каждый компонент решает свою задачу).
  • Упрощение тестирования и отладки.

Динамическая вставка компонентов

Riot.js позволяет динамически рендерить компоненты через условные блоки и циклы:

<user-list>
  <user-card each={user in users} name={user.name} age={user.age}></user-card>

  <script>
    export default {
      users: [
        { name: 'Иван', age: 30 },
        { name: 'Анна', age: 25 }
      ]
    }
  </script>
</user-list>
  • Атрибут each позволяет перебирать массив и создавать отдельный экземпляр дочернего компонента для каждого элемента.
  • Изменение массива users автоматически обновляет DOM благодаря реактивной системе Riot.js.

Передача слотов (контента) в дочерние компоненты

Riot.js поддерживает слоты, которые позволяют вставлять произвольный контент в дочерний компонент:

<card>
  <h2 slot="title">Заголовок карточки</h2>
  <p slot="body">Содержимое карточки</p>
</card>
<card>
  <div name="title"></div>
  <div name="body"></div>
</card>

<script>
  export default {}
</script>

Слоты обеспечивают гибкость: один и тот же компонент может отображать разный контент, не изменяя своей логики.


Советы по организации вложенных компонентов

  • Разделять компоненты на мелкие, переиспользуемые блоки.
  • Использовать props и события для минимизации прямых ссылок на родителя.
  • Применять слоты для кастомизации контента без дублирования кода.
  • Структурировать компоненты в папки по функциональным модулям для удобства навигации.

Вложенные компоненты и композиция позволяют создавать масштабируемые интерфейсы с четкой структурой и высокой поддерживаемостью. Riot.js предоставляет все необходимые инструменты для построения как простых, так и сложных веб-приложений, сохраняя при этом легковесность и реактивность.