上一个章节实现数据在组件之间的传递 。这一章主要是完成添加任务到任务栏、删除任务栏、统计任务完成情况。主要还是参数在各个组件之间的传递。
上一章节的链接地址:https://blog.csdn.net/weixin_43304253/article/details/126238030
文章目录
- 1、实现的效果演示
- 2、需求实现的大致流程
- 3 、代码(这里只给出主要部分代码、详细代码请看第一章节)
-
- 3.1 App.vue(省略了样式)
- 3.2 TheList.vue (省略了样式)
- 3.3 TheItem.vue(样式改进:删除按钮只有停留在对应行才会显示出来)
- 3.4 TheHeader.vue (省略了样式)
- 3.5 TheFooter.vue (省略了样式)
- 4、实现的效果
1、实现的效果演示
Vue组件实战应用完成任务功能演示
2、需求实现的大致流程
- 添加任务到任务栏:需要考虑TheHeader中的数据怎样传入到TheList组件中
- 删除一个任务:需要拿到待删除的任务主键标识、然后在数组对象中删除(遍历的形式)
- 勾选任务:根据对象中的勾状态、取反
- 初次加载勾选已完成任务:在checkbox中 根据任务的状态展示完成情况(checked)
- 统计任务完成情况:根据对象中的任务完成状态 遍历数组。累加计算
3 、代码(这里只给出主要部分代码、详细代码请看第一章节)
3.1 App.vue(省略了样式)
<template>
<div id="root">
<div class="todo-container">
<div class="todo-wrap">
<TheHeader :addTodo="addTodo" />
<TheList
:todos="todos"
:checkTodo="checkTodo"
:deleteTodo="deleteTodo"
/>
<TheFooter
:todos="todos"
:checkAllTodo="checkAllTodo"
:clearAllTodo="clearAllTodo"
/>
</div>
</div>
</div>
</template>
<script>
import TheHeader from "./components/TheHeader";
import TheList from "./components/TheList";
import TheFooter from "./components/TheFooter.vue";
export default {
name: "App",
components: { TheHeader, TheList, TheFooter },
data() {
return {
//由于todos是MyHeader组件和MyFooter组件都在使用,所以放在App中(状态提升)
todos: [
{ id: "001", title: "吃饭", done: true },
{ id: "002", title: "睡觉", done: false },
{ id: "003", title: "打豆豆", done: true },
],
};
},
methods: {
//添加一个todo
addTodo(todoObj) {
this.todos.unshift(todoObj);
},
//勾选or取消勾选一个todo
checkTodo(id) {
this.todos.forEach((todo) => {
if (todo.id === id) todo.done = !todo.done;
});
},
//删除一个todo
deleteTodo(id) {
this.todos = this.todos.filter((todo) => todo.id !== id);
},
//全选or取消全选
checkAllTodo(done) {
this.todos.forEach((todo) => {
todo.done = done;
});
},
//清除所有已经完成的todo
clearAllTodo() {
this.todos = this.todos.filter((todo) => {
return !todo.done;
});
},
},
};
</script>
3.2 TheList.vue (省略了样式)
<template>
<ul class="todo-main">
<TheItem
v-for="todoObj in todos"
:key="todoObj.id"
:todo="todoObj"
:checkTodo="checkTodo"
:deleteTodo="deleteTodo"
/>
</ul>
</template>
<script>
import TheItem from "./TheItem";
export default {
name: "TheList",
components: { TheItem },
//声明接收App传递过来的数据,其中todos是自己用的
props: ["todos", "checkTodo",'deleteTodo'],
};
</script>
3.3 TheItem.vue(样式改进:删除按钮只有停留在对应行才会显示出来)
<template>
<li>
<label>
<input
type="checkbox"
:checked="todo.done"
@change="handleCheck(todo.id)"
/>
<span>{
{ todo.title }}</span>
</label>
<button class="btn btn-danger" @click="handleDelete(todo.id)">删除</button>
</li>
</template>
<script>
export default {
name: "MyItem",
//声明接收todo、checkTodo、deleteTodo
props: ["todo", "checkTodo",'deleteTodo'],
methods: {
//勾选or取消勾选
handleCheck(id) {
//通知App组件将对应的todo对象的done值取反
this.checkTodo(id);
},
//删除
handleDelete(id) {
if (confirm("确定删除吗?")) {
//通知App组件将对应的todo对象删除
this.deleteTodo(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;
}
li:hover{
background-color: #ddd;
}
li:hover button{
display: block;
}
</style>
3.4 TheHeader.vue (省略了样式)
<template>
<div class="todo-header">
<input
type="text"
placeholder="请输入你的任务名称,按回车键确认"
v-model="title"
@keyup.enter="add"
/>
</div>
</template>
<script>
import { nanoid } from "nanoid";
export default {
name: "TheHeader",
//接收从App传递过来的addTodo
props:['addTodo'],
data() {
return {
//收集用户输入的title
title: "",
};
},
methods: {
add() {
//校验数据
if (!this.title.trim()) return alert("输入不能为空");
//将用户的输入包装成一个todo对象
const todoObj = { id: nanoid(), title: this.title, done: false };
//通知App组件去添加一个todo对象
this.addTodo(todoObj);
//清空输入
this.title = "";
},
},
};
</script>
3.5 TheFooter.vue (省略了样式)
<template>
<div class="todo-footer" v-show="total">
<label>
<!-- <input type="checkbox" :checked="isAll" @change="checkAll"/> -->
<input type="checkbox" v-model="isAll"/>
</label>
<span>
<span>已完成{
{doneTotal}}</span> / 全部{
{total}}
</span>
<button class="btn btn-danger" @click="clearAll">清除已完成任务</button>
</div>
</template>
<script>
export default {
name:'TheFooter',
props:['todos','checkAllTodo','clearAllTodo'],
computed: {
//总数
total(){
return this.todos.length
},
//已完成数
doneTotal(){
//此处使用reduce方法做条件统计
/* const x = this.todos.reduce((pre,current)=>{
console.log('@',pre,current)
return pre + (current.done ? 1 : 0)
},0) */
//简写
return this.todos.reduce((pre,todo)=> pre + (todo.done ? 1 : 0) ,0)
},
//控制全选框
isAll:{
//全选框是否勾选
get(){
return this.doneTotal === this.total && this.total > 0
},
//isAll被修改时set被调用
set(value){
this.checkAllTodo(value)
}
}
},
methods: {
/* checkAll(e){
this.checkAllTodo(e.target.checked)
} */
//清空所有已完成
clearAll(){
this.clearAllTodo()
}
},
}
</script>
4、实现的效果
整理不易、欢迎白嫖党一键三连 !!! 哈哈哈哈哈哈哈哈哈。曾经我也是白嫖党