FAST Element — это современная библиотека для создания веб-компонентов на JavaScript с реактивной системой обновления свойств и удобным шаблонным синтаксисом. Для построения динамичных приложений часто требуется интеграция с внешними источниками данных, такими как REST API, GraphQL, локальное хранилище или IndexedDB. Рассмотрим ключевые подходы к работе с внешними хранилищами.
В FAST Element свойства компонентов автоматически отслеживаются при изменении, что позволяет синхронизировать данные с интерфейсом. Основные моменты:
import { FASTElement, html, css, observable } from "@microsoft/fast-element";
class UserProfile extends FASTElement {
@observable user = null;
async fetchUser(id) {
const response = await fetch(`https://api.example.com/users/${id}`);
this.user = await response.json();
}
}
UserProfile.define({
name: "user-profile",
template: html<UserProfile>`
<div>
<h2>${x => x.user?.name}</h2>
<p>Email: ${x => x.user?.email}</p>
</div>
`,
styles: css`
h2 { color: #333; }
p { font-size: 14px; }
`
});
Ключевые моменты:
@observable обеспечивает реактивность. Любое изменение
свойства автоматически перерисовывает шаблон.fetch, могут напрямую
обновлять наблюдаемые свойства.${x => x.user?.name}, что защищает от ошибок при
null или undefined.Для REST API важно отделять логику запроса от визуальной части
компонента. Использование асинхронных методов и observable
свойств позволяет строить реактивный интерфейс:
class TodosList extends FASTElement {
@observable todos = [];
async connectedCallback() {
super.connectedCallback();
await this.loadTodos();
}
async loadTodos() {
const response = await fetch('https://jsonplaceholder.typicode.com/todos');
this.todos = await response.json();
}
}
TodosList.define({
name: 'todos-list',
template: html<TodosList>`
<ul>
${x => x.todos.map(todo => html`<li>${todo.title}</li>`)}
</ul>
`
});
Особенности:
connectedCallback используется для инициализации
данных при добавлении компонента в DOM.Для небольших данных можно синхронизировать observable
свойства с localStorage:
class SettingsPanel extends FASTElement {
@observable theme = 'light';
connectedCallback() {
super.connectedCallback();
this.theme = localStorage.getItem('theme') || 'light';
}
changeTheme(newTheme) {
this.theme = newTheme;
localStorage.setItem('theme', newTheme);
}
}
SettingsPanel.define({
name: 'settings-panel',
template: html<SettingsPanel>`
<button @click=${x => x.changeTheme('light')}>Light</button>
<button @click=${x => x.changeTheme('dark')}>Dark</button>
<p>Current theme: ${x => x.theme}</p>
`
});
Особенности синхронизации:
observable свойства и
localStorage поддерживаются в одном состоянии.Для сложных хранилищ подходит IndexedDB, обеспечивающий оффлайн-хранение и работу с большими объемами данных:
function openDatabase() {
return new Promise((resolve, reject) => {
const request = indexedDB.open('AppDB', 1);
request.onupgradenee ded = () => {
request.result.createObjectStore('users', { keyPath: 'id' });
};
request.onsucc ess = () => resolve(request.result);
request.oner ror = () => reject(request.error);
});
}
class IndexedUserList extends FASTElement {
@observable users = [];
async connectedCallback() {
super.connectedCallback();
await this.loadUsers();
}
async loadUsers() {
const db = await openDatabase();
const transaction = db.transaction('users', 'readonly');
const store = transaction.objectStore('users');
const request = store.getAll();
request.onsucc ess = () => { this.users = request.result; };
}
}
IndexedUserList.define({
name: 'indexed-user-list',
template: html<IndexedUserList>`
<ul>
${x => x.users.map(user => html`<li>${user.name}</li>`)}
</ul>
`
});
Особенности:
onsuccess/onerror.observable свойства позволяет
автоматически отобразить данные после их загрузки.GraphQL позволяет получать данные более гибко, чем REST, и часто используется с FAST Element для построения реактивных интерфейсов:
import { request } from 'graphql-request';
class GraphQLUser extends FASTElement {
@observable user = null;
async connectedCallback() {
super.connectedCallback();
const query = `
query getUser($id: ID!) {
user(id: $id) {
id
name
email
}
}
`;
this.user = await request('https://api.example.com/graphql', query, { id: 1 });
}
}
GraphQLUser.define({
name: 'graphql-user',
template: html<GraphQLUser>`
<div>
<h3>${x => x.user?.user.name}</h3>
<p>${x => x.user?.user.email}</p>
</div>
`
});
Особенности:
observable и асинхронных функций
обеспечивает автоматическое обновление интерфейса при загрузке
данных.@observable и реактивных
массивов: Любое изменение данных должно происходить через
реактивные свойства для автоматического обновления шаблона.try/catch.?.) и проверку наличия данных для
предотвращения ошибок при первичной отрисовке.Интеграция FAST Element с внешними хранилищами обеспечивает мощную реактивную систему и гибкость в построении сложных веб-приложений, позволяя сочетать преимущества компонентной архитектуры с динамическими источниками данных.