6. 添加列表数据
随机生成id,使用
nanoid
,安装nanoid
,npm i nanoid
导入
nanoid
,import {nanoid} from nanoid
使用
nanoid
,nanoid()
会返回一个唯一的字符串修改列表数据的存放位置为App.vue,便于数据的添加。
当前数据的传递方式
添加数据:
App组件将添加待做事项的方法传递给TodoAddTask组件,TodoAddTask组件调用父组件传递过来的方法添加待做事项,由于方法真正存在的位置为App组件,相当于TodoAddTask组件只是拥有方法的使用权。
App.vue
<template> <div class="todo-container"> <div class="todo-wrap"> <!-- 将添加待做事项的方法传入子组件中 --> <TodoAddTask :addTodo="addTodo"></TodoAddTask> <TodoList :todos="todos"></TodoList> <TodoSituation></TodoSituation> </div> </div> </template> <script> // 导入子组件 import TodoAddTask from './components/TodoAddTask.vue' import TodoList from './components/TodoList.vue' import TodoSituation from './components/TodoSituation.vue' export default { name: 'App', components: { TodoAddTask, TodoList, TodoSituation }, data() { return { todos: [ {id: '001', todo: '吃饭', done: true}, {id: '002', todo: '睡觉', done: false}, {id: '003', todo: '打豆豆', done: true} ] } }, methods: { // 将新的待做事项添加到列表中 addTodo(todo) { this.todos.unshift(todo) } }, } </script>
TodoList.vue
<template> <ul class="todo-main"> <!-- 将每个待做事项传入TodoItem --> <TodoItem v-for="todo in todos" :key="todo.id" :todoObj="todo" ></TodoItem> </ul> </template> <script> // 导入子组件 import TodoItem from './TodoItem.vue' export default { name: 'TodoList', components: {TodoItem}, props: ['todos'] } </script>
TodoAddTask.vue
<template> <div class="todo-header"> <input type="text" placeholder="请输入你的任务名称,按回车键确认" v-model="task" @keydown.enter="addTask" /> </div> </template> <script> // 导入nanoid import {nanoid} from 'nanoid' export default { name: 'TodoAddTask', props: ['addTodo'], data() { return { task: '' } }, methods: { addTask() { // 没有输入不进行添加 if (!this.task) return // console.log(this.task) // 新的待做事项 const todo = { id: nanoid(), todo: this.task, done: false } // 添加待做事项 this.addTodo(todo) // 输入框清空 this.task = '' } } } </script>
7. 勾选
由于数据在App组件中,所以修改数据中完成状态的方法也写在App组件中,然后将方法传递给子组件调用,子组件调用方法修改勾选状态。
App.vue
<template> <div class="todo-container"> <div class="todo-wrap"> <!-- 将添加待做事项的方法传入子组件中 --> <TodoAddTask :addTodo="addTodo"></TodoAddTask> <!-- 将数据和方法传入子组件 --> <TodoList :todos="todos" :changeDone="changeDone" ></TodoList> <TodoSituation></TodoSituation> </div> </div> </template> <script> // 导入子组件 import TodoAddTask from './components/TodoAddTask.vue' import TodoList from './components/TodoList.vue' import TodoSituation from './components/TodoSituation.vue' export default { name: 'App', components: { TodoAddTask, TodoList, TodoSituation }, data() { return { todos: [ {id: '001', todo: '吃饭', done: true}, {id: '002', todo: '睡觉', done: false}, {id: '003', todo: '打豆豆', done: true} ] } }, methods: { // 将新的待做事项添加到列表中 addTodo(todo) { this.todos.unshift(todo) }, // 修改待做事项的勾选状态 changeDone(id) { this.todos.forEach((todo)=>{ if (todo.id === id) todo.done = !todo.done }) } }, } </script>
TodoList.vue
<template> <ul class="todo-main"> <!-- 将每个待做事项传入TodoItem --> <!-- 将方法传递给子组件 --> <TodoItem v-for="todo in todos" :key="todo.id" :todoObj="todo" :changeDone="changeDone" ></TodoItem> </ul> </template> <script> // 导入子组件 import TodoItem from './TodoItem.vue' export default { name: 'TodoList', components: {TodoItem}, props: ['todos', 'changeDone'] } </script>
TodoItem.vue
<template> <li> <label> <!-- 使用v-bind绑定checked属性,true则有这个属性,false无这个属性 --> <input type="checkbox" :checked="todoObj.done" @click="changeChecked"/> <span>{{todoObj.todo}}</span> </label> <button class="btn btn-danger" style="display:none">删除</button> </li> </template> <script> export default { name: 'TodoItem', props: ['todoObj', 'changeDone'], methods: { // 修改勾选状态 changeChecked() { this.changeDone(this.todoObj.id) } }, } </script> <style scoped> /*item*/ li { list-style: none; height: 36px; line-height: 36px; padding: 0 5px; border-bottom: 1px solid #ddd; } li label { float: left; cursor: pointer; } li label li input { vertical-align: middle; margin-right: 6px; position: relative; top: -1px; } li button { float: right; display: none; margin-top: 3px; } li:before { content: initial; } li:last-child { border-bottom: none; } </style>
8. 删除
鼠标悬浮,对应的item项背景颜色改变,删除按钮显示。
TodoItem.vue
li:hover { background-color: #ddd; } li:hover button { display: inline-block; }
<button class="btn btn-danger" @click="handlerDelete">删除</button>
App.vue
<template> <div class="todo-container"> <div class="todo-wrap"> <!-- 将添加待做事项的方法传入子组件中 --> <TodoAddTask :addTodo="addTodo"></TodoAddTask> <!-- 将数据和方法传入子组件 --> <TodoList :todos="todos" :changeDone="changeDone" :deleteTodo="deleteTodo" ></TodoList> <TodoSituation></TodoSituation> </div> </div> </template> <script> // 导入子组件 import TodoAddTask from './components/TodoAddTask.vue' import TodoList from './components/TodoList.vue' import TodoSituation from './components/TodoSituation.vue' export default { name: 'App', components: { TodoAddTask, TodoList, TodoSituation }, data() { return { todos: [ {id: '001', todo: '吃饭', done: true}, {id: '002', todo: '睡觉', done: false}, {id: '003', todo: '打豆豆', done: true} ] } }, methods: { // 将新的待做事项添加到列表中 addTodo(todo) { this.todos.unshift(todo) }, // 修改待做事项的勾选状态 changeDone(id) { this.todos.forEach((todo)=>{ if (todo.id === id) todo.done = !todo.done }) }, // 删除todo deleteTodo(id) { this.todos = this.todos.filter((todo)=>{ return todo.id !== id }) } }, } </script>
TodoList.vue
<template> <ul class="todo-main"> <!-- 将每个待做事项传入TodoItem --> <!-- 将方法传递给子组件 --> <TodoItem v-for="todo in todos" :key="todo.id" :todoObj="todo" :changeDone="changeDone" :deleteTodo="deleteTodo" ></TodoItem> </ul> </template> <script> // 导入子组件 import TodoItem from './TodoItem.vue' export default { name: 'TodoList', components: {TodoItem}, props: ['todos', 'changeDone', 'deleteTodo'] } </script>
TodoItem.vue
<template> <li> <label> <!-- 使用v-bind绑定checked属性,true则有这个属性,false无这个属性 --> <input type="checkbox" :checked="todoObj.done" @click="changeChecked"/> <span>{{todoObj.todo}}</span> </label> <button class="btn btn-danger" @click="handlerDelete">删除</button> </li> </template> <script> export default { name: 'TodoItem', props: ['todoObj', 'changeDone', 'deleteTodo'], methods: { // 修改勾选状态 changeChecked() { this.changeDone(this.todoObj.id) }, // 删除 handlerDelete() { // 弹出框点击确定执行if中的代码 // 点击取消不执行 if (confirm('确定删除吗?')) { this.deleteTodo(this.todoObj.id) } } }, } </script>