48

是否有任何直接选项可以持久保存苗条的存储数据,以便即使刷新页面,数据也将可用。

我没有使用本地存储,因为我希望这些值是反应性的。

4

11 回答 11

64

您可以手动创建对商店的订阅并将更改持久保存到 localStorage,还可以使用 localStorage 中的潜在值作为默认值。

例子

<script>
  import { writable } from "svelte/store";
  const store = writable(localStorage.getItem("store") || "");

  store.subscribe(val => localStorage.setItem("store", val));
</script>

<input bind:value={$store} />
于 2019-06-07T07:30:15.377 回答
12

来自Matthias Stahl 的https://github.com/higsch/higsch.me/blob/master/content/post/2019-06-21-svelte-local-storage.md

假设我们有一个名为count.

// store.js
import { writable } from 'svelte/store';

export const count = writable(0);

// App.svelte
import { count } from 'store.js';

为了使存储持久化,只需将函数包含useLocalStoragestore对象中即可。

// store.js
import { writable } from 'svelte/store';

const createWritableStore = (key, startValue) => {
  const { subscribe, set } = writable(startValue);
  
  return {
    subscribe,
    set,
    useLocalStorage: () => {
      const json = localStorage.getItem(key);
      if (json) {
        set(JSON.parse(json));
      }
      
      subscribe(current => {
        localStorage.setItem(key, JSON.stringify(current));
      });
    }
  };
}

export const count = createWritableStore('count', 0);

// App.svelte
import { count } from 'store.js';

count.useLocalStorage();

然后,在您App.svelte刚刚调用该useLocalStorage函数以启用持久状态。

这在Routify中对我来说非常有效。对于Sapper,JHeth 建议“只需放置count.useLocalStorage()在使用存储的组件中onMountif (process.browser)组件中。”

于 2020-04-19T07:15:51.840 回答
9

对于 Svelte Kit,我遇到了 SSR 问题。这是我基于Svelte Kit FAQ的解决方案,Matyanson回答和 Adnan Y的回答。

作为奖励,此解决方案还会在localStorage发生更改时更新可写内容(例如,在不同的选项卡中)。所以这个解决方案可以跨标签工作。查看窗口:存储事件

将其放入打字稿文件中,例如$lib/store.ts

import { browser } from '$app/env';
import type { Writable } from 'svelte/store';
import { writable, get } from 'svelte/store'

const storage = <T>(key: string, initValue: T): Writable<T> => {
    const store = writable(initValue);
    if (!browser) return store;

    const storedValueStr = localStorage.getItem(key);
    if (storedValueStr != null) store.set(JSON.parse(storedValueStr));

    store.subscribe((val) => {
        if ([null, undefined].includes(val)) {
            localStorage.removeItem(key)
        } else {
            localStorage.setItem(key, JSON.stringify(val))
        }
    })

    window.addEventListener('storage', () => {
        const storedValueStr = localStorage.getItem(key);
        if (storedValueStr == null) return;

        const localValue: T = JSON.parse(storedValueStr)
        if (localValue !== get(store)) store.set(localValue);
    });

    return store;
}

export default storage

这可以像这样使用:

import storage from '$lib/store'

interface Auth {
    jwt: string
}

export const auth = storage<Auth>("auth", { jwt: "" })
于 2021-08-14T16:13:20.287 回答
3

如果有人需要使用 JavaScript 对象进行此操作:

export const stored_object = writable(
    localStorage.stored_object? JSON.parse(localStorage.stored_object) : {});
stored_object.subscribe(val => localStorage.setItem("stored_object",JSON.stringify(val)));

好处是您可以使用 $ 速记访问可写对象,例如

<input type="text" bind:value={$stored_object.name}>
<input type="text" bind:value={$stored_object.price}>
于 2021-02-01T15:03:26.330 回答
2

你可能还想看看这个https://github.com/andsala/svelte-persistent-store

另外,如果你使用 sapper 并且不想在服务器上运行某些东西,你可以使用 onMount 钩子

onMount(() => {
  console.log('I only run in the browser');
});
于 2020-03-08T06:06:22.950 回答
1

TLDR:这是一个不仅负责设置和获取,还负责删除的函数。

function persistent(name) {
    const value = writable(localStorage.getItem(name));
    value.subscribe(val => [null, undefined].includes(val) ? localStorage.removeItem(name) : localStorage.setItem(name, val));
    return value;
}


export const my_token = persistent('token');

推理:与直觉相反,localStorage.setItem('someval', null)不会为下一个设置 return null ,localStorage.getItem('someval')但这"null"可能不是人们想要的。因此,这也会检查 undefined 和 null 并相应地删除该项目。

于 2021-05-02T05:03:58.877 回答
1

此函数将 svelte store 与 localStorage 同步。如果没有存储值,则改为使用 initValue 参数。

我还添加了打字稿。

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

const wStorage = <T>(key: string, initValue: T): Writable<T> => {
    const storedValueStr = localStorage.getItem(key);
    const storedValue: T = JSON.parse(storedValueStr);

    const store = writable(storedValueStr != null ? storedValue : initValue);
    store.subscribe((val) => {
        localStorage.setItem(key, JSON.stringify(val));
    })
    return store;
}

export default wStorage;

然后,您可以像以前一样在其他地方使用该功能writable

const count = wStorage<number>('count', 0);

编辑:如果您在应用程序中使用 SSR 并且不想使用onMount或检查if (process.browser)每个可写方法。这是修改后的版本:

const wStorage = <T>(key: string, initValue: T): Writable<T> => {
    const store = writable(initValue);
    if (typeof Storage === 'undefined') return store;

    const storedValueStr = localStorage.getItem(key);
    if (storedValueStr != null) store.set(JSON.parse(storedValueStr));

    store.subscribe((val) => {
        localStorage.setItem(key, JSON.stringify(val));
    })
    return store;
}
于 2021-05-19T19:08:56.457 回答
1

使用svelte 3.38svelte-kitSapper的继任者),我使用:

<script>
  import { onMount } from 'svelte';
  import { writable } from "svelte/store";

  let value;

  onMount(() => {
    value = writable(localStorage.getItem("storedValue") || "defaut value");
    value.subscribe(val => localStorage.setItem("storedValue", val));
  })
</script>

<input bind:value={$value} />

localStorage不可用onMount()

于 2021-07-22T07:53:31.637 回答
1

在此处输入图像描述

这是我书中的一个示例,希望对您有所帮助。

于 2022-01-14T11:08:14.127 回答
0

适合我的苗条版本3.44.1

src/store.js 文件:

import { writable } from "svelte/store";
import { browser } from "$app/env"

export const fontSize = writable(browser && localStorage.getItem("fontSize") || "15");
fontSize.subscribe((value) => {
    if (browser) return localStorage.setItem("fontSize", value)
});

于 2021-11-13T11:51:23.517 回答
0

下面是使用 Typescript 的示例。此示例允许您获取初始值订阅未来更新和设置值。

不要忘记在onDestroy()中调用unsubscribe( )

创建一个文件:local-storage.ts

type Invalidator<T> = (value?: T) => void;

interface WritableLocalStorage<T> {
  readonly value: T;

  subscribe(this: void, run: Subscriber<T>, invalidate?: Invalidator<T>): Unsubscriber;
  set(this: void, value: T): void;
}

export const useLocalStorage = <T>(key: string, initialValue?: T): WritableLocalStorage<T> => {
  const item = localStorage?.getItem(key);
  const value: T = item ? JSON.parse(item) : initialValue;

  const { set, subscribe } = writable(value);

  return {
    value,
    subscribe,
    set: (val) => {
      localStorage?.setItem(key, JSON.stringify(val));
      set(val);
    }
  };
};

内部苗条文件:

const { set, subscribe, value } = useLocalStorage<string[]>('items', []);

// get initial value from localStorage
let items = value;

// subscribe and retrieve future updates
const unsubscribe = subscribe(val => {
  items = val;
});

// set value
set(['item1']);

// unsubscribe when component gets destroyed
onDestroy(() => unsubscribe());
于 2022-03-01T20:31:10.993 回答