当前位置:网站首页>Todolist classic case ①
Todolist classic case ①
2022-07-01 07:19:00 【18 hate programming】
List of articles
Case introduction
As shown in the figure below :
There are a few small details :
When all events are checked , The following has been completed, and the previous box will also be checked automatically
Only after at least one event is selected , Will appear “ Clear completed tasks ” The button

When there are no to-do events in the list , The completed line will not be displayed as a whole

The added event appears at the top of the list
The case requires
Use the front end frame Vue Realization
And does not use the global event bus 、 Knowledge about message subscription and publication
case analysis
First of all, according to componentization, we must split this to-do list . Of course, there are many ways to disassemble , I recommend two :
- It's divided into three parts :

- Divided into four parts

Here I use the second method , We name each component :
- Red part components – headers.vue
- Green part components – tasks.vue
- Pink part components – task.vue
- Blue components – record.vue
Code implementation
App Components
<template>
<div id="app">
<Headers :addTasks="addTasks" :getLength="getLength"></Headers>
<Tasks :tasks="tasks" :updateTasks="updateTasks" :deleteTask="deleteTask"> </Tasks>
<Record :tasks="tasks" :getFinished="getFinished" :deleteAll="deleteAll" :selectAll="selectAll"></Record>
</div>
</template>
<script> import Headers from './components/headers' import Tasks from './components/tasks' import Record from './components/record' export default {
name: 'App', components: {
Headers, Tasks, Record }, data() {
return {
tasks: [ {
id: 1, inform: ' sleep ', completed: true}, {
id: 2, inform: ' having dinner ', completed: false}, {
id: 3, inform: ' Drink lots of water ', completed: true}, // Note here is the demonstration data , Delete in real time , Otherwise you may report an error . According to the code logic , If you delete one , Add another , Will appear // Two id by 3 The data of , Then the operation will be confused . // Be careful : there tasks Data can be transferred directly ] } }, methods: {
addTasks(task) {
this.tasks.unshift(task) console.log(this.tasks) }, getLength() {
return this.tasks.length }, updateTasks(id) {
for (let i = 0; i < this.tasks.length; i++) {
if (this.tasks[i].id === id) {
this.tasks[i].completed = !this.tasks[i].completed } } }, getFinished() {
let sum = 0 for (let i = 0; i < this.tasks.length; i++) {
if (this.tasks[i].completed == true) {
sum++ } } return sum }, deleteTask(id) {
this.tasks = this.tasks.filter(value => {
return value.id !== id }) }, deleteAll() {
this.tasks = this.tasks.filter(value => {
return value.completed == false }) }, selectAll(obj) {
// Note that what we want to discuss here is the situation after pressing the button if (obj.checked == true) {
for (let i = 0; i < this.tasks.length; i++) {
this.tasks[i].completed = true } } else {
for (let i = 0; i < this.tasks.length; i++) {
this.tasks[i].completed = false } } }, } } </script>
<style> #app {
width: 400px; text-align: center; border-width: 2px; border-color: #eaeaea; border-style: solid; border-radius: 10px; } </style>
Be careful :
- Consider that several components may use tasks data , So we put it in the parent component of these components App in , This facilitates the transfer of data
- tasks There are several demonstration data . Delete in real time , Otherwise you may report an error . According to the code logic , If you delete one , Add another , There will be two id by 3 The data of , Then the operation will be confused .
- We use props To realize the function of transferring data from parent component to child component
- If the child component wants to pass data to the parent component , We first define a method in the parent component , Pass to subcomponent , Then let the sub component call
- Although it USES the data Function of , But here tasks It can also be used directly props Delivered
- Show the data that does not need to be modified directly props Just go ; If you want to change the data , Where the data is, the method is
headers Components
<template>
<input type="text" class="read" placeholder=" Press down Enter Add to do event " @keydown.enter="addTask" v-model="task">
</template>
<script> export default {
name: "MyHeader", props:['addTasks','getLength'], data(){
return {
task:'', } }, methods:{
addTask(){
this.addTasks( {
id:this.getLength()+1,inform:this.task,completed:false} ) this.task='' }, } } </script>
<style scoped> .read {
width:370px; margin-top: 20px; border: 2px solid #e3e2e2; border-radius: 10px; height: 25px; font-size: 20px; color: orange; } </style>
Be careful :
- After entering the to-do event , Press down enter After adding , The input box should be cleared
tasks Components
<template>
<div>
<ul id="form" v-for="task in tasks" :key="task.id">
<Task :task="task" :updateTasks="updateTasks" :deleteTask="deleteTask"></Task>
</ul>
</div>
</template>
<script> import Task from "@/components/task"; export default {
name: "MyTasks", props:['tasks','updateTasks','deleteTask'], components:{
Task } } </script>
<style scoped> #form {
list-style-type: none; padding: 0px; } </style>
Be careful :
- Used v-for The tag of cannot be used as the root tag , So here I use div Another layer
task Components
<template>
<li class="tasks" >
<input type="checkbox" class="select" :checked="task.completed" @click="handleTask(task.id)">{
{task.inform}}<button class="delete" @click="deleteOne(task.id)"> Delete </button>
</li>
</template>
<script> export default {
name: "MyTask", props:['task','updateTasks','deleteTask'], methods:{
handleTask(id){
this.updateTasks(id) }, deleteOne(id){
this.deleteTask(id) } }, } </script>
<style scoped> li {
text-align: left; width: 370px; margin: 0 auto; border: 2px solid #e3e2e2; height: 30px; line-height: 30px; } li:hover {
background-color: #dcdcdc; visibility: visible; } li:hover .delete {
visibility: visible; } .delete {
height: 30px; color: white; background-color: red; border-radius: 5px; visibility: hidden; float: right; } </style>
When doing this part , The difficulty must be how to act on specific elements . How do you understand that ? That is, after we click the check box in front of an item , How can we accurately modify his data ? adopt id that will do , Because we put the callback method of click event in App In the component , So this is the process of transferring data from the child component to the parent component , We define the method in the parent component , And pass it to the sub components , Then the method is called by the sub component , Pass in data while calling , In this way, you can accurately pass id Operate to the corresponding data .
record Components
<template>
<div class="record" v-show="tasks.length != 0">
<!-- :checked="finish == tasks.length && tasks.length > 0 " This is to delete the blank list , Uncheck the -->
<input type="checkbox" :checked="getFinished() == tasks.length && tasks.length > 0 " ref="checkAll" @click="selectAll($refs.checkAll)">
Completed {
{getFinished()}}/ All {
{tasks.length}}
<!-- Show this data that doesn't need to be changed directly props Just go , If you want to change the data , Where the data is, the method is -->
<!-- v-show If your expression is a method , So this method is to bring () Of -->
<button class="delete" @click="deleteAllTasks" v-show="ifShow()"> Clear completed tasks </button>
</div>
</template>
<script> export default {
name: "MyRecord", props:['getFinished','deleteAll','selectAll','tasks'], methods:{
deleteAllTasks(){
this.deleteAll() this.$refs.fuyuan.checked = false }, ifShow(){
for (let i = 0; i < this.tasks.length; i++) {
if(this.tasks[i].completed === true) return true } return false } } } </script>
<style scoped> .record {
width:370px; margin:0 auto; text-align: left; height: 35px; } .delete {
height: 30px; color: white; background-color: red; border-radius: 5px; /*visibility: hidden;*/ float: right; } </style>
Be careful :
- v-show If your expression is a method , So this method is to bring () Of
There is no need to ref To get DOM node , We can also use the click event object target Property to get the element directly , Let me introduce two commonly used vue Method to get the event object in :
Method ①:$event keyword ( It is applicable when the event callback function has foreign parameters )
Method ②: Write the callback function name directly ( It is applicable to the event callback function without external parameters )
Case summary
summary TodoList Case study
Componentized coding process :
(1). Split static components : Components should be split according to function points , Do not name with html Element conflict .
(2). Implement dynamic components : Consider where the data is stored , Data is a component in use , Some components are still in use :
1). A component is in use : Just put it on the component itself .
2). Some components are in use : On their common parent component ( Status up ).
(3). Implement interaction : Start with binding events .
props Apply to :
(1). Parent component ==> Child components signal communication
(2). Child components ==> Parent component signal communication ( Ask the parent to give the child a function first )
Use v-model Remember to :v-model Bound value cannot be props Transmitted value , because props It can't be modified !
props If the value of the object type is passed , When modifying properties in an object Vue No mistake. , But this is not recommended .
边栏推荐
猜你喜欢

如何画产品架构图?

Introduction to spark (one article is enough)

Mysql与Redis一致性解决方案

【LINGO】求解二次规划
![[programming training] delete public characters (hash mapping) + team competition (greedy)](/img/cd/63eb9da1e8956df0763797f079b67f.png)
[programming training] delete public characters (hash mapping) + team competition (greedy)

Ctfhub port scan (SSRF)

JAX的深度学习和科学计算
![[image processing] image histogram equalization system with GUI interface](/img/3b/52c241c48c91dd58300af58478129e.png)
[image processing] image histogram equalization system with GUI interface

【Flutter 问题系列第 72 篇】在 Flutter 中使用 Camera 插件拍的图片被拉伸问题的解决方案

【LINGO】求无向图的最短路问题
随机推荐
[lingo] solve quadratic programming
C# 读写自定义的Config文件
redisson使用全解——redisson官方文档+注释(上篇)
为什么这么多人转行产品经理?产品经理发展前景如何?
C语言实现【三子棋游戏】(步骤分析和实现源码)
【编程强训3】字符串中找出连续最长的数字串+数组中出现次数超过一半的数字
Reply and explanation on issues related to "online training of network security education in 2022"
热烈祝贺五行和合酒成功挂牌
Image style migration cyclegan principle
Stepsister becomes stepmother, son breaks off relationship with himself, and musk, the world's richest man, why is it so miserable?
[image processing] image histogram equalization system with GUI interface
Is it reliable to open an account on the compass with your mobile phone? Is there any potential safety hazard
Apple账号密码自动填充
C语言实现【扫雷游戏】完整版(实现源码)
Understanding of Turing test and Chinese Room
MySQL table partition creation method
转行做产品经理,如何挑选产品经理课程?
How to create an exclusive vs Code theme
【电气介数】电气介数及考虑HVDC和FACTS元件的电气介数计算
How to choose a product manager course when changing to a product manager?


