苗条的反应性

Svelte Reactivity

尝试将使用 localStorage 的简单教程转换为使用 IndexedDB,但在反应性方面遇到问题。在我刷新页面之前,电影列表不会更新。谁能指出我正确的方向?谢谢!

下面的代码更新了 Thomas Hennes 在其中一个答案中建议的一些更改,谢谢!但是仍然需要手动刷新页面的问题。还添加了 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 持有解析为一系列电影的承诺,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>