Svelte 变量不会在不使用 setInterval 强制更新的情况下从 localStorage 更新。

huangapple go评论82阅读模式
英文:

Svelte variable not updating from localStorage without using setInterval and forcing it

问题

我有一个应用程序,它将项目存储在localStorage中的位置,然后在HTML中显示这些项目。

我之所以想使用Svelte,其中一个原因是它具有响应式变量,但无论我尝试使用一个当localStorage.current_items发生变化时也会改变的响应式变量时,ItemList变量都不会发生变化。

唯一能让它工作的方法是使用setInterval,但这不是一个好的做法。我该如何使ItemList在localStorage.current_items字符串更改时正确地发生变化?

<script lang="ts">
	import {
		getData,
		createItem,
		createLocation,
		closeItem,
	} from './lib/database.js';
	import LocationSelector from './lib/LocationSelector.svelte';
	import { flip } from 'svelte/animate';
	import { writable } from 'svelte/store';

	let DB = getData();
	// 从localstorage.items加载项目

	let ItemList = [];
	let Location;

	setInterval(() => {
		Location = localStorage.current_items;
		ItemList = JSON.parse(localStorage.current_items).items;
	}, 500);

	console.log(ItemList);

	let newItem = '';
	let filter_showClosed = false;

	function addNewItem(e) {
		e.preventDefault();
		console.log(newItem);
		const newItemInput = document.querySelector(
			'#newItemInput'
		) as HTMLInputElement;

		createItem(JSON.parse(Location).id, newItem);
		newItem = '';
	}

	function newItemKeyDown(e) {
		if (e.keyCode === 13) {
			addNewItem(e);
		}
	}
</script>

<LocationSelector />

<div class="app">
	<input
		type="text"
		id="newItemInput"
		bind:value={newItem}
		placeholder="Add a new item"
		on:keydown={newItemKeyDown}
	/>
	<button
		id="filter_showClosed"
		data-active="false"
		on:click={function () {
			filter_showClosed = !filter_showClosed;
			let el = document.getElementById('filter_showClosed');
			if (filter_showClosed) {
				el.innerHTML = 'Hide closed';
				el.dataset.active = 'true';
			} else {
				el.innerHTML = 'Show closed';
				el.dataset.active = 'false';
			}
		}}>Show closed</button
	>

	<div class="list">
		{#each ItemList as item, index (item.id)}
			<div class="item {item.closed}" animate:flip={{ duration: 100 }}>
				{#if item.closed == false || (filter_showClosed == true && item.closed == true)}
					<div>
						<img
							src="/up.svg"
							class="item-icon"
							class:closed={item.closed == true}
							alt="move item up in priority"
							on:click={function () {
								// increaseLevel({ item });
							}}
						/>
						{item.name} ({index})
					</div>
					<div>
						{#if item.closed == false}
							<img
								src="/close.svg"
								class="item-icon"
								alt="close item"
								on:click={function () {
									console.log(Location.id);
									closeItem(JSON.parse(Location).id, item.id);
								}}
							/>
						{/if}
					</div>
				{/if}
			</div>
		{/each}
	</div>
</div>

<style>
</style>

我尝试使用了writable方法,但这也没有起作用,因为变量仍然没有发生变化。

import { writable } from 'svelte/store';

const ItemList = writable([]);
let Location = {};

let newItem = '';
let filter_showClosed = false;

function addNewItem(e) {
	e.preventDefault();
	console.log(newItem);
	const newItemInput = document.querySelector(
		'#newItemInput'
	) as HTMLInputElement;

	createItem(Location.id, newItem);
	newItem = '';
}

function newItemKeyDown(e) {
	if (e.keyCode === 13) {
		addNewItem(e);
	}
}

// 使用localStorage.current_items的当前值更新Location对象为一个对象
Location = JSON.parse(localStorage.current_items);

// 使用新位置的项目更新ItemList存储
ItemList.set(Location.items);
英文:

I have an app that stores items into locations in localStorage and then displays the items in HTML.

One of the reasons i wanted to use Svelte was for reactive variables, but whenever I attempt to use a reactive variable that changes whenever localStorage.current_items changes, the ItemList variable doesn't change.

The only way I could get it to work is by using setInterval but that is not a great way to do it. How can I make it so that ItemList changes properly when the localStorage.current_items string changes.

&lt;script lang=&quot;ts&quot;&gt;
import {
getData,
createItem,
createLocation,
closeItem,
} from &#39;./lib/database.js&#39;;
import LocationSelector from &#39;./lib/LocationSelector.svelte&#39;;
import { flip } from &#39;svelte/animate&#39;;
import { writable } from &#39;svelte/store&#39;;
let DB = getData();
// load items from localstorage.items
let ItemList = [];
let Location;
setInterval(() =&gt; {
Location = localStorage.current_items;
ItemList = JSON.parse(localStorage.current_items).items;
}, 500);
console.log(ItemList);
let newItem = &#39;&#39;;
let filter_showClosed = false;
function addNewItem(e) {
e.preventDefault();
console.log(newItem);
const newItemInput = document.querySelector(
&#39;#newItemInput&#39;
) as HTMLInputElement;
createItem(JSON.parse(Location).id, newItem);
newItem = &#39;&#39;;
}
function newItemKeyDown(e) {
if (e.keyCode === 13) {
addNewItem(e);
}
}
&lt;/script&gt;
&lt;LocationSelector /&gt;
&lt;div class=&quot;app&quot;&gt;
&lt;input
type=&quot;text&quot;
id=&quot;newItemInput&quot;
bind:value={newItem}
placeholder=&quot;Add a new item&quot;
on:keydown={newItemKeyDown}
/&gt;
&lt;button
id=&quot;filter_showClosed&quot;
data-active=&quot;false&quot;
on:click={function () {
filter_showClosed = !filter_showClosed;
let el = document.getElementById(&#39;filter_showClosed&#39;);
if (filter_showClosed) {
el.innerHTML = &#39;Hide closed&#39;;
el.dataset.active = &#39;true&#39;;
} else {
el.innerHTML = &#39;Show closed&#39;;
el.dataset.active = &#39;false&#39;;
}
}}&gt;Show closed&lt;/button
&gt;
&lt;!-- &lt;button
id=&quot;deleteClosed&quot;
on:click={function () {
let it = items;
for (let i = 0; i &lt; it.length; i++) {
if (it[i].closed == true) {
it.splice(i, 1);
}
}
items = it;
sort_items(items);
}}&gt;Delete all closed&lt;/button
&gt; --&gt;
&lt;div class=&quot;list&quot;&gt;
{#each ItemList as item, index (item.id)}
&lt;div class=&quot;item {item.closed}&quot; animate:flip={{ duration: 100 }}&gt;
{#if item.closed == false || (filter_showClosed == true &amp;&amp; item.closed == true)}
&lt;div&gt;
&lt;img
src=&quot;/up.svg&quot;
class=&quot;item-icon&quot;
class:closed={item.closed == true}
alt=&quot;move item up in priority&quot;
on:click={function () {
// increaseLevel({ item });
}}
/&gt;
{item.name} ({index})
&lt;/div&gt;
&lt;div&gt;
{#if item.closed == false}
&lt;img
src=&quot;/close.svg&quot;
class=&quot;item-icon&quot;
alt=&quot;close item&quot;
on:click={function () {
console.log(Location.id);
closeItem(JSON.parse(Location).id, item.id);
}}
/&gt;
{/if}
&lt;/div&gt;
{/if}
&lt;/div&gt;
{/each}
&lt;/div&gt;
&lt;/div&gt;
&lt;style&gt;
&lt;/style&gt;

I tried using this writeable method, but that didn't work either as the variable still didn't change.

import { writable } from &#39;svelte/store&#39;;
const ItemList = writable([]);
let Location = {};
let newItem = &#39;&#39;;
let filter_showClosed = false;
function addNewItem(e) {
e.preventDefault();
console.log(newItem);
const newItemInput = document.querySelector(
&#39;#newItemInput&#39;
) as HTMLInputElement;
createItem(Location.id, newItem);
newItem = &#39;&#39;;
}
function newItemKeyDown(e) {
if (e.keyCode === 13) {
addNewItem(e);
}
}
// Update the Location object with the current value of localStorage.current_items as an object
Location = JSON.parse(localStorage.current_items);
// Update the ItemList store with the new location&#39;s items
ItemList.set(Location.items);

答案1

得分: 0

你应该使用一个完全封装了对 localStorage 访问的存储器。

类似这样的方式:

function localStorageStore(key, 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;
}

读取和写入就像普通的存储器一样,但在初始加载时,值来自存储,并且在设置值时,它也会写入存储。

英文:

You should use a store that fully wraps the access to localStorage.

Something like:

function localStorageStore(key, initial) {
    const value = localStorage.getItem(key)
    const store = writable(value == null ? initial : JSON.parse(value));
    store.subscribe(v =&gt; localStorage.setItem(key, JSON.stringify(v)));
    
    return store;
}

Reading and writing is just a regular store, but on initial load the value comes from the storage and on setting the value, it is also written to storage.

huangapple
  • 本文由 发表于 2023年1月9日 03:51:26
  • 转载请务必保留本文链接:https://go.coder-hub.com/75050813.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定