Slim.js — это легковесная библиотека для создания веб-компонентов, ориентированная на декларативный подход и реактивность. Одной из ключевых задач при работе с компонентами является загрузка данных на этапе их монтирования. Slim.js предоставляет удобные хуки жизненного цикла, которые позволяют выполнить асинхронные операции и инициализировать состояние компонента до его отображения.
onBeforeMountКаждый компонент Slim.js проходит через несколько фаз жизненного
цикла. Для загрузки данных непосредственно перед отображением
используется хук onBeforeMount. В этом
методе выполняются операции, которые должны завершиться до того, как DOM
компонента будет полностью смонтирован:
import Slim from 'slim-js';
class UserProfile extends Slim {
static get observedAttributes() { return ['userId']; }
onBeforeMount() {
this.userData = null;
this.loadUserData(this.getAttribute('userId'));
}
async loadUserData(userId) {
const response = await fetch(`https://api.example.com/users/${userId}`);
this.userData = await response.json();
this.update(); // Перерисовывает шаблон после получения данных
}
get template() {
return `
<div>
${this.userData ? `<h2>${this.userData.name}</h2>` : `<p>Загрузка...</p>`}
</div>
`;
}
}
Slim.define('user-profile', UserProfile);
Ключевые моменты:
onBeforeMount вызывается один раз
перед первичной отрисовкой.this.update(),
чтобы обновить DOM.onMount для асинхронной инициализацииХук onMount вызывается после того, как
компонент уже добавлен в DOM. Это удобно, если данные можно загружать
параллельно с отображением или если требуется доступ к реальному
DOM-элементу компонента:
class TodoList extends Slim {
todos = [];
onMount() {
this.fetchTodos();
}
async fetchTodos() {
const response = await fetch('https://api.example.com/todos');
this.todos = await response.json();
this.update();
}
get template() {
return `
<ul>
${this.todos.map(todo => `<li>${todo.title}</li>`).join('')}
</ul>
`;
}
}
Slim.define('todo-list', TodoList);
Особенности использования onMount:
this.shadowRoot или
this.querySelector.Slim.js автоматически отслеживает свойства компонента, изменяя DOM
при вызове this.update(). При загрузке данных важно
правильно управлять состоянием:
class WeatherWidget extends Slim {
weather = null;
isLoading = true;
onMount() {
this.loadWeather();
}
async loadWeather() {
const response = await fetch('https://api.weather.com/v1/current');
this.weather = await response.json();
this.isLoading = false;
this.update();
}
get template() {
return this.isLoading
? `<p>Загрузка погоды...</p>`
: `<div>Температура: ${this.weather.temp}°C</div>`;
}
}
Slim.define('weather-widget', WeatherWidget);
Выводы по работе с состоянием:
isLoading) позволяет управлять
визуальной частью компонента.this.update()
инициирует реактивное обновление DOM.Асинхронные операции могут завершиться ошибкой. Для стабильности приложения важно обрабатывать исключения и отображать соответствующее состояние:
class PostsList extends Slim {
posts = [];
error = null;
onMount() {
this.fetchPosts();
}
async fetchPosts() {
try {
const response = await fetch('https://api.example.com/posts');
if (!response.ok) throw new Error('Ошибка загрузки');
this.posts = await response.json();
} catch (err) {
this.error = err.message;
} finally {
this.update();
}
}
get template() {
if (this.error) return `<p>Ошибка: ${this.error}</p>`;
if (!this.posts.length) return `<p>Загрузка...</p>`;
return `<ul>${this.posts.map(p => `<li>${p.title}</li>`).join('')}</ul>`;
}
}
Slim.define('posts-list', PostsList);
Важные аспекты:
try/catch/finally для безопасной
загрузки данных.this.update() для перерисовки.onBeforeMount для загрузки до отображения,
onMount для работы с DOM.fetch или других API с async/await.this.update().try/catch,
чтобы компонент корректно реагировал на сбои.Slim.js делает процесс интеграции асинхронных данных в компоненты простым и предсказуемым, позволяя создавать динамичные и отзывчивые интерфейсы без лишнего кода.