苗条的反应性
Posted
技术标签:
【中文标题】苗条的反应性【英文标题】:Svelte Reactivity 【发布时间】:2021-05-26 13:18:33 【问题描述】:尝试将使用 localStorage 的简单教程转换为使用 IndexedDB,但反应性有问题。在我刷新页面之前,电影列表不会更新。谁能指出我正确的方向?谢谢!
以下代码已更新,其中一个答案是 Thomas Heennes 建议的一些更改,谢谢!仍然有需要手动页面刷新的问题。还添加了 MovieList.svelte
App.svelte
<script>
import MovieInput from "./MovieInput.svelte";
import MovieList from "./MovieList.svelte";
import Search from "./Search.svelte";
import db from "./db.js";
import Dexie from "dexie";
//get a promise containing all movies in IndexedDB (if collection exists)
let movies = db.movies.count(function (value)
return (movies = value > 0 ? db.movies.toArray() : []);
);
//add new item to IndexedDb
const submitMovie = (movie) =>
db.movies.put( title: movie.title, rating: movie.rating );
;
</script>
<div class="main">
<h1>Movie Journal</h1>
<MovieInput on:submitMovie=(event) => submitMovie(event.detail.movie) />
#await movies
<div>Loading movies...</div>
:then movieArray
<MovieList movieArray />
:catch error
<div>Error loading movies: error.message</div>
/await
</div>
<style>
.main
width: 500px;
max-width: 100%;
padding: 1em;
margin: auto;
text-align: center;
h1
color: #ff3e00;
text-transform: uppercase;
font-size: 4em;
font-weight: 100;
</style>
添加 MovieList 也可能是我做错了什么:
还有 MovieList.svelte
<script>
export let movieArray;
</script>
#each movieArray as movie
<div>
<h3>movie.title</h3>
<p>Your Rating: movie.rating</p>
</div>
/each
<style>
div
text-align: left;
padding-bottom: 10px;
border-bottom: 1px solid black;
</style>
【问题讨论】:
考虑将声明movies = db.movies.count ...
重构为更简单的 movies = loadMovies()
以避免在初始加载和添加电影后的刷新操作之间重复代码。
实际上,当我开始实现搜索功能时,我也这样做了!在我的问题末尾添加了更新的代码。感觉有点没必要一直获取数据库,所以在搜索时考虑使用一些临时数组,但目前它至少可以工作:)
【参考方案1】:
如果movies
持有可解析为电影数组的承诺,则 Svelte 方法是使用 #await ...
块:
<script>
import MovieInput from "./MovieInput.svelte";
import MovieList from "./MovieList.svelte";
import Search from "./Search.svelte";
import db from "./db.js";
import Dexie from "dexie";
// not needed, the resulting data array will be created within the
// #await ... block
// let movieArray = [];
//get a promise containing all movies in IndexedDB (if collection exists)
let movies = db.movies.count(function (value)
return (movies = value > 0 ? db.movies.toArray() : []);
);
// not needed, use an #await ... block to handle resolution or error
// push items in promise to movieArray
// movies
// .then((movies) =>
// movies.forEach(function (movie)
// movieArray.push(movie);
// );
// )
// .catch((error) =>
// console.log(error);
// ).finally(() =>
// movieArray = movieArray;
// );
//add new item to IndexedDb
const submitMovie = (movie) =>
db.movies.put( title: movie.title, rating: movie.rating );
;
</script>
<div class="main">
<h1>Movie Journal</h1>
<MovieInput on:submitMovie=(event) => submitMovie(event.detail.movie) />
#await movies
<div>Loading movies...</div>
:then movieArray
<MovieList movieArray />
:catch error
<div>Error loading movies: error.message</div>
/await
</div>
<style>
...
</style>
【讨论】:
嗨!谢谢,这确实删除了一些代码并且看起来更好,并且我已经验证它可以像这样工作,但是列表仍然需要手动页面刷新才能在屏幕上更新。 更新是什么意思?如果您正在更改数据库的内容并期望页面自动刷新,那么它不会发生。还是说初始渲染时列表为空,需要手动刷新页面才能看到数据? 现在我因为没有看到它而感到愚蠢:D 我只是在页面加载时获取集合,当然它不会更新,除非我刷新页面。感谢您指出! 感谢您提及我的小托马斯,我添加了在提交新项目时再次获取收藏,现在它(至少在视觉上)可以按我的意愿工作。以上是关于苗条的反应性的主要内容,如果未能解决你的问题,请参考以下文章