【问题标题】:Svelte app bug: uncompleted todos are not returnedSvelte 应用程序错误:未完成的待办事项未返回
【发布时间】:2021-05-17 14:30:08
【问题描述】:

我正在使用 Svelte 开发一个小型待办事项应用程序。我列出了来自 jsonplaceholder 的 10 个待办事项。

我要统计completed属性等于false的todos:

const apiURL = "https://jsonplaceholder.typicode.com/todos";
const limit = 10;
import { onMount } from "svelte";
import TodoItem from './TodoItem.svelte';
let todos = [];
let unsolvedTodos = [];

onMount(() => {
    getTodos();
});

const getTodos = () => {
    fetch(`${apiURL}?&_limit=${limit}`)
    .then(res => res.json())
    .then((data) => todos = data);
}

const getUnsolvedTodos = () => {
    unsolvedTodos = todos.filter(todo => {
        return todo.completed === false;
    })
}

$:console.log(unsolvedTodos);

this REPL 中可以看出,unsolvedTodos 数组是空的。


编辑

我得到了未解决的待办事项列表及其长度,但我不能在标题组件中使用它。

const getTodos = () => {
    fetch(`${apiURL}?&_limit=${limit}`)
    .then(res => res.json())
    .then((data) => todos = data)
    .then(getUnsolvedTodos);
}

const getUnsolvedTodos = () => {
    unsolvedTodos = todos.filter(todo => {
        return todo.completed === false;
    })
}

$:console.log(unsolvedTodos.length); 

在 REPL 中可见,使用 <span class="count">{unsolvedTodos.length}</span> 会引发 unsolvedTodos is not defined 错误,尽管我导入了 ToDoList。

我的错误在哪里?

【问题讨论】:

  • 你在任何地方调用你的函数getUnsolvedTodosTodos吗?
  • @devnull69 在$:console.log(unsolvedTodos) 行中。
  • 不,这只是记录 unsolvedTodos 的内容,但根本没有调用函数
  • @devnull69 请查看我的编辑(问题)。

标签: javascript svelte


【解决方案1】:

简单地将一个组件导入另一个组件不会暴露其属性。所以你不能做import TodoList from './TodoList.svelte'; 并期望 unsolvedTodos 在标题中可用。您可以使用的只有 组件 TodoList。从您的代码中,您似乎在尝试访问未定义变量 todosTodoItem 中犯了同样的错误。

您在这里面临的问题是您需要在彼此没有直接关系的两个或多个组件之间共享数据(它们不是父子节点)。在此类组件之间共享数据通常通过以下两种方式之一解决:

通过父母

第一个解决方案是将状态或数据移动到父级。在您的情况下,这意味着待办事项的实际列表以及有关添加、删除、切换等的所有逻辑都存储在 App.svelte 中,而其他组件只是您的 表示组件通过此列表。

<script>
  import TodoList from './TodoList.svelte';

  let todos = []
  // Here comes logic for fetching the list and changing the state
</script>

<TodoList todos={todos} />

正如您在此处看到的,App 负责跟踪待办事项,而 List 组件只会显示它们。如果你想在列表中添加一个新项目,你会在 here 而不是在 TodoList 中这样做 如果你改变一个项目的状态,你必须冒泡它一直到 App.svelte 并且不更改 TodoItem 中的状态,即纯粹显示当前状态。

最后一部分有点麻烦,所以更好的选择可能是

使用商店

使用 [stores][1] 您可以定义一个点来保持您的状态,然后将该状态导入到需要它的组件中,例如 TodoList 将是:

<script>
  import { todos } from './store.js';
  import TodoItem from './TodoItem.svelte';
</script>

{#each $todos as todo}
  <TodoItem todo={todo} />
{/each}

类似地,TodoItem 可以导入这个商店并更新列表中的响应元素。 (最好是为此使用自定义存储,因此所有逻辑现在都真正驻留在存储对象中)。

【讨论】:

  • 你会如何(重新)做这个小项目?最好的方法是什么?
  • 使用存储方式
  • 为什么我必须切换来自App. svelte 组件的待办事项?每个组件不应该有自己的逻辑吗?
  • 这是一个组织问题,区分表示和业务逻辑是很常见的,你当然可以把它放在组件本身,但你仍然必须以某种方式将更改传播到源数据,这样整个应用的整体状态是正确的。
【解决方案2】:

不要使用函数来计算,而是使用过滤器代码内联并以 $ 前缀使其具有反应性

$: unsolvedTodos = todos.filter(todo => { 返回 todo.completed === false; });

并在模板中使用这个值

【讨论】:

    猜你喜欢
    • 2023-03-20
    • 1970-01-01
    • 2020-09-02
    • 1970-01-01
    • 2020-11-13
    • 2017-06-07
    • 2020-05-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多