上一個章節實現數據在組件之間的傳遞 。這一章主要是完成添加任務到任務欄、刪除任務欄、統計任務完成情況。主要還是參數在各個組件之間的傳遞。
上一章節的鏈接地址:
文章目錄
- 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、實現的效果
整理不易、歡迎白嫖黨一鍵三連 !!! 哈哈哈哈哈哈哈哈哈。曾經我也是白嫖黨
本文章為轉載內容,我們尊重原作者對文章享有的著作權。如有內容錯誤或侵權問題,歡迎原作者聯繫我們進行內容更正或刪除文章。