Estoy tratando de crear elementos de almacenamiento local a partir de un objeto de objetos usando localStorage
.
A continuación puedes ver el código con más detalles:
// FILE: settings.js // Imported by my main file +page.svelte and the Settings.svelte component. The selected property of each object is bound to a select html element inside Settings.svelte. import { browser } from '$app/env'; import { writable} from 'svelte/store'; export const settings = writable({ speed: { options: ['slow', 'medium', 'fast'], // Each selected property of an object should be bound to a localStorage // Example: speedLocal : 'slow' selected: 'slow' }, sound: { options: ['on', 'off'], selected: 'on' }, tiles: { options: [4, 6, 8], selected: 4 }, theme: { options: ['light', 'dark'], selected: 'light' }, })
En primer lugar, no es una buena idea mezclar un estado mutable con valores fijos como este. No hay razón para que las opciones existan en un almacén writable
si no pueden cambiar.
En cuanto a cómo hacer que esto sea más conveniente: puede almacenar todos los valores en un solo objeto y serializarlo como JSON.
El ejemplo más básico:
import { browser } from '$app/env'; import { readable, writable } from 'svelte/store'; function localStorageStore(key, initial) { if (browser == false) return readable(initial); const value = localStorage.getItem(key) const store = writable(value == null ? initial : JSON.parse(value)); store.subscribe(v => localStorage.setItem(key, JSON.stringify(v))); return store; } const options = { speed: ['slow', 'medium', 'fast'], sound: ['on', 'off'], tiles: [4, 6, 8], theme: ['light', 'dark'], } const settings = localStorageStore('so.lss', { speed: 'slow', sound: 'on', tiles: 4, theme: 'light', });
Dado que el acceso a localStorage
está encapsulado en una función de todos modos, también podría crear fácilmente una tienda para cada opción individualmente.
Si desea una forma genérica de usar opciones y configuraciones juntas, puede iterar a través de Object.entries
, por ejemplo
{#each Object.entries(options) as [key, items]} <select bind:value={$settings[key]}> {#each items as item} <option value={item}>{item}</option> {/each} </select> {/each}
Nota: La implementación de la tienda es solo para fines ilustrativos. Probablemente desee un mecanismo más complejo que maneje:
Date
, ya que no se analizarán de nuevo a una Date
.storage
, si la tienda debe sincronizarse en varias pestañas.Si debe mantener ese formato de objeto, también puede volver a asignarlo a sus componentes:
const configuration = { speed: { options: ['slow', 'medium', 'fast'], selected: 'slow' }, sound: { options: ['on', 'off'], selected: 'on' }, tiles: { options: [4, 6, 8], selected: 4 }, theme: { options: ['light', 'dark'], selected: 'light' }, }; const options = Object.fromEntries( Object.entries(configuration) .map(([key, value]) => [key, value.options]) ); const settings = localStorageStore( 'so.lss', Object.fromEntries( Object.entries(configuration) .map(([key, value]) => [key, value.selected]) ) );
Las options
/ settings
serán equivalentes al primer ejemplo.