我正在使用 Svelte 开发一个小型待办事项应用程序。我从 jsonplaceholder 列出了 10 个待办事项。
我想计算 completed
属性等于 false
的待办事项:
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。
我的错误在哪里?
答案 0 :(得分:2)
不要使用函数来计算,而是使用内联过滤器代码和前缀 $ 使其具有反应性
$: unsolvedTodos = todos.filter(todo => { 返回 todo.completed === false; });
并在模板中使用这个值
答案 1 :(得分:2)
简单地将一个组件导入另一个组件不会暴露其属性。因此,您不能执行 import TodoList from './TodoList.svelte';
并期望 unsolvedTodos 在标题中可用。您所拥有的只是组件 TodoList。从您的代码来看,您似乎在 TodoItem 中尝试访问未定义的变量 todos
时犯了同样的错误。
您在这里面临的问题是您需要在彼此没有直接关系的两个或多个组件(它们不是父子组件)之间共享数据。在此类组件之间共享数据通常通过以下两种方式之一解决:
通过父母
第一个解决方案是将状态或数据移动到父级。在您的情况下,这意味着实际的待办事项列表以及有关添加、删除、切换等的所有逻辑...都存储在 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 组件只会显示它们。如果你想在列表中添加一个新项目,你可以在这里而不是在 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 可以导入此存储并更新列表中的响应元素。 (最好为此使用自定义存储,以便所有逻辑现在都驻留在存储对象中)。