当前位置:网站首页>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 .
边栏推荐
- 【系统分析师之路】第五章 复盘软件工程(逆向净室与模型驱动开发)
- Webapck packaging principle -- Analysis of startup process
- 华泰证券开户是安全可靠的么?怎么开华泰证券账户
- 【微服务|openfeign】Feign的日志记录
- Système de gestion de l'exploitation et de l'entretien, expérience d'exploitation humanisée
- Paging in servlets and JSPS
- Cadence OrCAD Capture “网络名”相同,但是未连接或连接错误的解放方案之nodename的用法
- [Shenzhen IO] precise Food Scale (some understanding of assembly language)
- [the path of system analysts] Chapter 5: software engineering of double disk (reverse clean room and Model Driven Development)
- MySQL table partition creation method
猜你喜欢
C# Newtonsoft.Json中JObject的使用
[programming compulsory training 3] find the longest consecutive number string in the string + the number that appears more than half of the times in the array
JSP - 分页
关于图灵测试和中文屋Chinese room的理解
Mysql与Redis一致性解决方案
ctfshow-web355,356(SSRF)
[chapter 72 of the flutter problem series] a solution to the problem that pictures taken in the flutter using the camera plug-in are stretched
為什麼這麼多人轉行產品經理?產品經理發展前景如何?
【LINGO】求解二次规划
Challenges faced by operation and maintenance? Intelligent operation and maintenance management system to help you
随机推荐
【Flutter 问题系列第 72 篇】在 Flutter 中使用 Camera 插件拍的图片被拉伸问题的解决方案
AI视频智能平台EasyCVR设备录像出现无法播放现象的问题修复
Inventory the six second level capabilities of Huawei cloud gaussdb (for redis)
[lingo] find the shortest path problem of undirected graph
redisson看门狗机制,redisson看门狗性能问题,redisson源码解析
Chinese explanation of common rclone subcommands
How the esp32 deep sleep current is lower than 10uA
ctfhub-端口扫描(SSRF)
Code practice - build your own diffusion models / score based generic models from scratch
Rclone access web interface
运维管理系统,人性化操作体验
转行做产品经理,如何挑选产品经理课程?
iNFTnews | 从《雪崩》到百度“希壤”,元宇宙30年的16件大事
[lingo] solve quadratic programming
赌上了绩效,赢了公司CTO,我要搭DevOps平台!
【推荐系统】美团外卖推荐场景的深度位置交互网络DPIN的突破与畅想
华泰证券开户是安全可靠的么?怎么开华泰证券账户
ctfshow-web351(SSRF)
【目标检测】目标检测界的扛把子YOLOv5(原理详解+修炼指南)
EasyNVS云管理平台功能重构:支持新增用户、修改信息等