题目:
使用Vue3编写一个简单的待办事项列表,其中可以添加、删除、完成和编辑每个任务。要求使用Composition API实现,同时考虑性能优化和代码可读性。
答案:
下面是一个可能的实现,其中包含注释来解释代码的主要部分:
<template>
<div class="todo-list">
<!-- 输入新任务的表单 -->
<form @submit.prevent="addTodo">
<input v-model="newTodoText" placeholder="Add a new task" />
<button type="submit">Add</button>
</form>
<!-- 待办事项列表 -->
<ul>
<li v-for="(todo, index) in todos" :key="todo.id" :class="{ completed: todo.completed, editing: todo.id === editingTodoId }">
<div class="view">
<input class="toggle" type="checkbox" v-model="todo.completed" />
<label @dblclick="editTodo(todo.id)">{
{ todo.text }}</label>
<button class="destroy" @click="deleteTodo(index)"></button>
</div>
<form @submit.prevent="saveTodo">
<input class="edit" v-if="todo.id === editingTodoId" v-model="editedTodoText" />
</form>
</li>
</ul>
<!-- 显示已完成的任务数量 -->
<div class="completed-count">
<p>{
{ completedCount }} tasks completed</p>
</div>
</div>
</template>
<script>
import { reactive, computed } from 'vue';
export default {
setup() {
// 使用reactive创建一个响应式的todos对象,其中包含每个任务的文本、完成状态和唯一ID
const todos = reactive([
{ id: 1, text: 'Learn Vue', completed: false },
{ id: 2, text: 'Build a Todo app', completed: true },
]);
// 用于跟踪正在编辑的任务的ID
const editingTodoId = reactive(null);
// 用于存储新任务文本的变量
const newTodoText = reactive('');
// 用于存储编辑后任务文本的变量
const editedTodoText = reactive('');
// 计算已完成任务的数量
const completedCount = computed(() => todos.filter(todo => todo.completed).length);
// 向todos数组添加新任务
const addTodo = () => {
const newTodo = {
id: todos.length + 1,
text: newTodoText,
completed: false,
};
todos.push(newTodo);
newTodoText.value = '';
};
// 删除特定索引的任务
const deleteTodo = index => {
todos.splice(index, 1);
};
// 开始编辑特定ID的任务
const editTodo = id => {
editingTodoId.value = id;
const todo = todos.find(todo => todo.id === id);
editedTodoText.value = todo.text;
};
// 保存特定ID的任务
const saveTodo = () => {
const todo = todos.find(todo => todo.id === editingTodoId.value);
todo.text = editedTodoText.value;
editingTodoId.value = null;
};
return {
todos,
editingTodoId,
newTodoText,
editedTodoText,
completedCount
};
},
};
</script>
<style>
.completed {
text-decoration: line-through;
}
.editing .view {
display: none;
}
.editing .edit {
display: block;
width: 100%;
}
</style>
上面的代码创建了一个简单的待办事项列表,包括一个表单来添加新任务,一个列表来显示当前所有任务,以及一个计数器来显示已完成的任务数量。它使用Composition API来创建响应式的数据和处理函数,并且考虑了性能和可读性方面的优化。
其中,reactive
函数创建了一个响应式的todos
数组,包含每个任务的文本、完成状态和唯一ID。computed
函数创建了一个计算属性completedCount
,用于计算已完成的任务数量。在组件中,我们使用了v-for
指令遍历todos
数组,并将每个任务渲染为列表项。我们还使用了v-model
指令来绑定表单元素和响应式数据,以及一些事件监听器来处理用户的输入和操作。
在性能方面,我们尽可能使用了响应式数据,避免了不必要的重新渲染。我们还使用了key
属性来帮助Vue跟踪每个列表项的状态,以便在更新列表时提高性能。此外,我们还使用了computed
函数来缓存计算结果,避免了不必要的计算。
在可读性方面,我们使用了清晰的命名和注释,以便其他开发者能够轻松理解代码。我们还使用了ES6的语法来简化代码,例如箭头函数和解构赋值。
扩展
为什么要使用Composition API,而不是Options API?
答:Composition API具有更好的组织性和可复用性,可以将相关的代码组合在一起,使代码更易于理解和维护。它也可以提高代码的可测试性,因为我们可以更轻松地测试单个函数和组合函数。此外,Composition API还提供了更好的TypeScript支持,可以在编译时捕获更多的类型错误。
在哪里使用reactive函数,为什么?
答:reactive函数用于将一个普通JavaScript对象转换为响应式的数据对象,这样当对象的属性发生变化时,Vue可以自动检测并更新视图。在上述代码中,我们使用reactive函数来创建一个响应式的todos数组,使其能够自动更新列表项和计数器。
computed函数的作用是什么,何时使用它?
答:computed函数用于创建计算属性,这是一种依赖于其他响应式数据的属性。当依赖的数据发生变化时,计算属性会自动重新计算,并且只在必要时才更新。在上述代码中,我们使用computed函数来创建一个计算属性completedCount,用于计算已完成的任务数量。
为什么要使用key属性,有什么作用?
答:key属性用于帮助Vue跟踪每个列表项的状态,以便在更新列表时提高性能。Vue通过key属性来判断哪些元素需要更新、删除或添加。如果没有key属性,Vue将使用默认的索引作为key,这会导致在列表中添加或删除项时出现意外的行为。
如何添加新的待办事项,以及如何将任务标记为已完成或未完成?
答:可以通过表单元素和v-model指令来添加新的待办事项,其中绑定的数据为newTodo。在列表项中,我们使用了复选框来标记任务的完成状态,它的绑定值为todo.completed。当复选框的值发生变化时,会触发toggleTodo函数,该函数会将任务的完成状态取反。
如何删除待办事项,以及如何编辑已有任务?
答:可以通过单击删除按钮来删除待办事项,它会触发deleteTodo函数,该函数会将任务从todos数组中删除。要编辑已有任务,可以先双击任务文本,将该任务设置为“编辑”状态,此时任务文本会转换为一个文本框,让用户可以输入新的任务文本。当用户完成编辑后,可以按下Enter键或失去焦点来保存更改,或按下Esc键来取消编辑。