компилируется...
Перейти к основному содержанию
Рекомендовать во Вконтакте Рекомендовать в Фейсбуке Рекомендовать в Твиттере

Управление состоянием между компонентами в Svelte

Как работать с Props, контекстным API и хранилищем (Store) в Svelte, чтобы передать состояние в вашем приложении между компонентами.

Svelte очень легко справляется с состоянием одного компонента. Но как мы передаем состояние между компонентами?

Передача состояния с помощью props

Первая стратегия является общей для других UI фреймворков, и она передает состояние с помощью ствойств, поднимая состояние вверх.

Когда одному компоненту требуется обмен данными с другим, состояние может быть перемещено вверх по дереву компонентов до тех пор, пока не появится общий родитель для этих компонентов.

Состояние должно передаваться до тех пор, пока оно не достигнет всех компонентов, которые нуждаются в этой информации о состоянии.
Это делается с помощью свойств (props), и это техника, которая, как я думаю, является лучшей, так как она проста.

Контекстный API

Есть случаи, когда props не практичен. Возможно, 2 компонента настолько удалены друг от друга в дереве компонентов, что нам пришлось бы переместить состояние на верхний уровень компонента.

В этом случае может использоваться другая техника, называемая контекстным API, и она идеальна, когда вы хотите, чтобы несколько компонентов общались с потомками, но вы не хотите передавать props.

Контекстный API обеспечивается 2 функциями, которые предоставляет пакет svelte: getContext и setContext.

Вы устанавливаете объект в контексте, связывая его с ключом:

<script>
import { setContext } from 'svelte';

const someObject = {};

setContext('someKey', someObject);
</script>

В другом компоненте вы можете использовать getContext для получения объекта, назначенного ключу:

<script>
import { getContext } from 'svelte';

const someObject = getContext('someKey');
</script>

Вы можете использовать getContext получения значения ключа, либо в компоненте, который использовал setContext, либо в компоненте, который является его потомком.

Если вы хотите, чтобы два компонента, живущие в двух разных деревьях компонентов, общались друг с другом, есть еще один инструмент для нас: хранилища (stores).

Использование хранилищ в Svelte

Хранилища Svelte - отличный инструмент для работы с вашим состоянием приложений, когда компоненты должны общаться друг с другом, не перегружая себя свойствами (props).

Сначала необходимо импортировать writable из svelte/store:

import { writable } from 'svelte/store';

и создадим переменную хранения с помощью функции writeable(), передав значение по умолчанию в качестве первого аргумента:

const username = writable('Guest');

Его можно поместить в отдельный файл, который можно импортировать в несколько компонентов, например store.js (это не компонент, поэтому он может быть в .js файле, а не .svelte:

import { writable } from 'svelte/store';
export const username = writable('Guest');

Любой другой компонент, загружающий этот файл, может получить доступ к хранилищу:

<script>
import { username } from './store.js';
</script>

Теперь значение этой переменной может быть установлено в новое значение с помощью функции set(), передавая новое значение в качестве первого аргумента:

username.set('new username');

И его можно обновить с помощью функции update(), которая отличается от функции set() не только тем, что вы передаете ему новое значение - вы запускаете функцию обратного вызова, которая передает в качестве аргумента текущее значение:

const newUsername = 'new username!';
username.update(existing => newUsername);

Здесь вы можете добавить больше логики:

username.update(existing => {
  console.log(`Updating username from ${existing} to ${newUsername}`);
  return newUsername;
});

Для однократного получения значения переменной можно воспользоваться функцией get(), экспортируемой из svelte/store:

import { readable, get } from 'svelte/store';
export const username = writable('Guest');
get(username) //'Guest';

Вместо этого, чтобы создать реактивную переменную, которая обновляется всякий раз, когда она изменяется, вы можете добавить переменную хранилища, используя $, в этом примере $username. Использование этого приведет к повторной визуализации компонента при каждом изменении сохраненного значения.

Svelte считает $ резервным значением и не позволит вам использовать его для вещей, которые не связаны со значениями хранилищ (и которые могут привести к путанице), поэтому если вы привыкли добавлять ссылки на DOM, используя $, не делайте этого в Svelte. Другой вариант, который лучше всего подходит, если вам нужно выполнить некоторую логику при изменении переменной, заключается в использовании метода subscribe() для username:

username.subscribe(newValue => {
 console.log(newValue);
});

В дополнение к хранилищам с возможностью записи, Svelte предлагает 2 специальных вида хранилищ: для чтения (readable stores) и производные хранилища (derived stores).

Svelte хранилища для чтения

Хранилища, доступные для чтения, являются особыми, потому что их нельзя обновлять извне - нет метода set() или update(). Вместо этого, как только вы установите исходное значение, его нельзя будет изменить извне.

Официальная документация Svelte показывает интересный пример использования таймера для обновления даты. Я могу подумать о настройке таймера для получения ресурсов из сети, выполнения вызова API, получения данных из файловой системы (с помощью локального сервера Node.js) или чего-то еще, что может быть настроено автономно.

В этом случае вместо использования функции writeable() для инициализации переменной store, мы используем функцию readable():

import { readable } from 'svelte/store';
export const count = readable(0);

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

<script>
import { readable } from 'svelte/store';
export const count = readable(0, set => {
  setTimeout(() => {
    set(1);
  }, 1000);
})
</script>

В этом случае мы обновляем значение от 0 до 1 через 1 секунду. В этой функции также можно задать интервал:

import { readable, get } from 'svelte/store';

export const count = readable(0, set => {
  setInterval(() => {
    set(get(count) + 1);
  }, 1000);
})

Вы можете использовать это в другом компоненте, подобном этому:

<script>
import { count } from './store.js';
</script>

{$count}

Производные хранилища Svelte

Производное хранилище позволяет создавать новое значение, которое зависит от значения существующего хранилища.

Это можно сделать с помощью derived() функции, экспортируемой из svelte/store, которая принимает в качестве первого параметра существующее значение хранилища, а в качестве второго параметра функцию, которая получает это значение хранилища как свой первый параметр:

import { writable, derived } from 'svelte/store';

export const username = writable('Guest');

export const welcomeMessage = derived(username, $username => {
  return `Welcome ${$username}`;
});
<script>
import { username, welcomeMessage } from './store.js'
</script>

{$username}
{$welcomeMessage}

Комментарии

Пока что нет комментариев, вы можете быть первым.
Войти или Регистрация , чтобы оставлять комментарии.

Лучшие публикации

Популярные теги

Наш сайт использует куки. Узнайте больше о нашем использовании куки: политика в отношении файлов cookie
Наш сайт существует только благодаря показу онлайн-рекламы нашим посетителям.
Пожалуйста, поддержите нас, отключив блокировку рекламы.