Сохранение данных между страницами

Stimulus — это JavaScript-фреймворк, ориентированный на добавление поведения к уже существующей HTML-разметке. В отличие от SPA-подходов, он не управляет навигацией и жизненным циклом страниц целиком. Каждая перезагрузка страницы уничтожает состояние контроллеров, поэтому сохранение данных между страницами требует явных решений на уровне браузера или сервера.

Задача сохранения данных между страницами возникает при работе с фильтрами, настройками интерфейса, временными пользовательскими вводами, состоянием UI и навигацией по многостраничным приложениям.


Использование URL как источника состояния

Самый простой и прозрачный способ сохранения данных — кодирование состояния в URL-параметрах. Stimulus-контроллеры могут читать и обновлять параметры строки запроса, синхронизируя их с состоянием интерфейса.

<div data-controller="filters">
  <SELECT data-action="change->filters#update">
    <option value="all">Все</option>
    <option value="active">Активные</option>
  </select>
</div>
import { Controller } FROM "@hotwired/stimulus"

export default class extends Controller {
  UPDATE(event) {
    const params = new URLSearchParams(window.location.search)
    params.se t("status", event.target.value)
    window.location.search = params.toString()
  }

  connect() {
    const params = new URLSearchParams(window.location.search)
    const status = params.get("status")
    if (status) {
      this.element.querySelector("select").value = status
    }
  }
}

Ключевые особенности подхода:

  • состояние переживает перезагрузку страницы;
  • URL остаётся источником истины;
  • легко воспроизводится и кешируется;
  • подходит для фильтров и навигации.

Ограничение — объём и чувствительность данных, которые нежелательно хранить в URL.


LocalStorage как клиентское хранилище

localStorage предоставляет постоянное хранилище данных в браузере, доступное между страницами и сессиями. Stimulus-контроллеры могут сохранять и восстанавливать состояние при подключении.

export default class extends Controller {
  static targets = ["input"]

  connect() {
    const saved = localStorage.getItem("search")
    if (saved) {
      this.inputTarget.value = saved
    }
  }

  save() {
    localStorage.setItem("search", this.inputTarget.value)
  }
}
<div data-controller="search">
  <input data-search-target="input"
         data-action="input->search#save">
</div>

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

  • данные сохраняются между страницами и перезапусками браузера;
  • синхронный API;
  • подходит для настроек интерфейса и пользовательских предпочтений.

Минусы — отсутствие автоматической синхронизации между вкладками и невозможность хранения сложных структур без сериализации.


SessionStorage для временных данных

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

connect() {
  const draft = sessionStorage.getItem("draft")
  if (draft) {
    this.element.value = draft
  }
}

save() {
  sessionStorage.setItem("draft", this.element.value)
}

Подходит для:

  • черновиков форм;
  • временных состояний UI;
  • пошаговых процессов.

Cookies и Stimulus

Cookies используются реже из-за ограниченного размера и сложности API, но иногда необходимы для серверной интеграции.

Stimulus не предоставляет встроенных средств для работы с cookies, но может использовать стандартный Jav * aScript:

document.cookie = "theme=dark; path=/; max-age=31536000"
const theme = document.cookie
  .split("; ")
  .find(row => row.startsWith("theme="))
  ?.split("=")[1]

Cookies уместны, если состояние должно быть доступно серверу при каждом запросе.


Сохранение состояния через сервер

В классических многостраничных приложениях состояние часто сохраняется на сервере — в сессии или базе данных. Stimulus в этом случае выступает как тонкий слой над HTML.

Пример: форма с автосохранением через AJAX.

export default class extends Controller {
  save() {
    fetch("/draft", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ text: this.element.value })
    })
  }
}

Сервер возвращает сохранённое состояние при рендеринге следующей страницы, а Stimulus продолжает работу с уже готовыми данными.


Использование data-атрибутов как точки передачи состояния

HTML-атрибуты data-* позволяют передавать серверные данные в клиентский код без дополнительных запросов.

<div data-controller="profile"
     data-profile-name-value="Alex"
     data-profile-age-value="30">
</div>
export default class extends Controller {
  static values = {
    name: String,
    age: Number
  }

  connect() {
    console.log(this.nameValue, this.ageValue)
  }
}

Этот подход особенно полезен при навигации между страницами, где сервер уже знает состояние и может встроить его в HTML.


Совмещение подходов

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

  • URL — для навигационного состояния;
  • localStorage — для пользовательских настроек;
  • сервер — для бизнес-данных;
  • data-* — для передачи состояния при рендеринге.

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


Архитектурные принципы

Изоляция контроллеров Каждый контроллер должен отвечать только за своё состояние и способ его сохранения.

Явность источника данных Состояние должно иметь один основной источник: URL, браузерное хранилище или сервер.

Минимизация глобального состояния Отсутствие общего store — сознательное решение Stimulus. Сохранение данных между страницами должно быть простым и предсказуемым.

Сервер как часть системы Stimulus предполагает тесную интеграцию с серверным рендерингом, где сохранение данных между страницами часто решается без JavaScript вовсе.


Сохранение данных между страницами в Stimulus — это не отдельный механизм, а набор практик, опирающихся на стандартные возможности браузера и сервера. Именно эта простота делает подход масштабируемым и удобным для учебных и промышленных приложений.