Vue(七) TodoList案例1.0

news/2024/9/16 7:20:49/ 标签: vue.js, 前端, javascript

文章目录

  • 组件化编码流程(通用)
  • 1. 拆分静态组件
  • 2. 初始化列表
    • 展示动态数据
    • 如何让一个标签动态的拥有某一个属性
  • 3. 按回车添加todo
    • 子组件给父组件传值之props
  • 4. 勾选与取消勾选一个Todo
  • 5. 删除
  • 6. footer底部统计
  • 7. footer底部交互
    • 7.1 全选框自动打勾
    • 7.2 全选框取消勾选
  • 8. 清除已完成任务
  • 总结

组件化编码流程(通用)

1、实现静态组件:抽取组件,使用组件实现静态页面效果

2、展示动态数据:

  • 数据的类型、名称是什么
  • 数据保存再哪个组件

3、交互–从绑定事件监听开始

如果组件名字不好起,想一下是不是组件拆分的不合理

1. 拆分静态组件

根据功能,可划分为以下几个组件:
在这里插入图片描述
将已写好页面的html,css根据组件进行拆分,得到的文件结构如下:
App组件里使用了MyHeader、MyList、MyFooter组件
在这里插入图片描述
MyList组件里使用了MyItem组件:
在这里插入图片描述

2. 初始化列表

展示动态数据

(1) 确定数据名称、数据类型
数据名称:这一堆的代办事项数据名称可以叫todos,
数据类型:最好用数组存储这一堆的待办事项,而每一个代办事项可以用对象存储。

(2) 数据保存在哪个组件:
谁用这些数据,就写在哪个组件里后续如果有变化,再改变位置。因此暂时写在MyList组件里。
MyList.vue

<template><ul class="todo-main"><!-- 循环生成多个MyItem,且将具体的代办事项传递给MyItem,否则还是页面的列表里还是yyyy--><MyItem v-for="toboObj in todos" :key="toboObj.id" :todo="toboObj" /></ul>
</template>
<script>javascript">
...data () {return {todos: [{ id: '0001', title: '吃饭', done: true },{ id: '0002', title: '睡觉', done: true },{ id: '0003', title: '打豆豆', done: false }]}}
</script>

MyItem.vue

<template><li><label><!-- 添加checked属性,初始化复选框的数据 --><input type="checkbox" checked /><span>{{ todo.title }}</span></label><button class="btn btn-danger" style="display: none">删除</button></li>
</template><script>javascript">
export default {name: 'MyItem',// 接收MyList组件传递的对象props: ["todo"]
}
</script>

但是添加checked后,所有的复选框都被勾选了。

如何让一个标签动态的拥有某一个属性

答:v-bind动态绑定

  <input type="checkbox" :checked="todo.done" />

在这里插入图片描述

3. 按回车添加todo

输入框在Header组件中,因此Header组件中要添加点击事件

<template><div class="todo-header"><!-- v-model获取表单元素的值 --><input type="text" placeholder="请输入你的任务名称,按回车键确认" v-model="title" @keydown.enter="add"/></div>
</template>

add回调函数中要做以下几件事:

javascript">import { nanoid } from 'nanoid'
methods: {add () {// 1. 获取到表单元素的内容console.log(this.title); // 或者通过 e.target.value获取到输入框的内容// 2. 将用户的输入包装成一个todo对象const todoObj = { id: nanoid(), title: this.title, done: false }  // 3. 将todo对象添加到todo列表里,即todos数组中// 4. 输入框内容置空。this.title = '' // 或者 e.target.value = '' }
}
  • nanoid
    包装的对象应该有一个唯一的id,uuid这个库可以生成全球唯一的编码,但是太大且生成的编码复杂。采用uuid的精简版:nanoid

    安装npm i nanoid
    引用 import {nanoid} from 'nanoid'
    使用: nanoid()(这是个函数,直接调用即可)

  • todoObj在MyHeader组件里,而数据todos在MyList组件里。两组件为兄弟组件,目前还不会兄弟组件之间通信。所以还是采用props属性。
    为了方便MyHeader通信,将todos改放在App组件里,而不是MyList组件里。此时:
    在这里插入图片描述

App可通过props将todos交给MyList组件进行展示。MyHeader该如何将todoObj交给父组件App呢?

子组件给父组件传值之props

父组件给子组件传递带参的函数

<!--App.vue-->
<template>...<!-- 给子组件传函数 --><MyHeader :addTodo="addTodo"></MyHeader><!-- 给子组件传数据 --><MyList :todos="todos"></MyList><MyFooter></MyFooter>...
</template>
<script>javascript">methods: {// 添加todoObjaddTodo (todoObj) {this.todos.unshift(todoObj)}}
}
</script>

子组件接收函数

<!--MyHeader.vue-->
<script>javascript">props: ["addTodo"],methods: {add () {//完善一下:校验数据if (!this.title.trim()) return alert('输入不能为空')const todoObj = { id: nanoid(), title: this.title, done: false }// 调用函数,通过参数将todoObj传递给父组件this.addTodo(todoObj)this.title = ''}}
}
</script>

总结:子组件向父组件传值时,父组件需提前向子组件传递一个带参的函数,子组件通过函数的参数将数据传给父组件。

捋顺一下流程:
1、按下回车,执行MyHeader里的add函数,在add里调用了App组件里的addTodo函数。
2、addTodo函数修改了App组件中data里的todos数据。
3、Vue捕获到todos变了,于是重新解析App里的template模板,重新解析时,将变化后的todos交给了MyList组件。
4、MyList收到数据,重新解析自己组件内的模板,v-for,虚拟DOM对比,更新页面。

4. 勾选与取消勾选一个Todo

在这里插入图片描述

MyItem.vue添加change事件(@click也可以)

  <input  type="checkbox"  :checked="todo.done" @change="handleCheck(todo.id)" />

handleCheck事件里需要对todos数据进行修改。数据在App组件里, 数据在哪里,操作数据的方法就在哪里,所以这里需要把待修改的todo的id传递给App。子组件给父组件传值,父组件需要先传递一个带参函数。此处应该是App传给MyList,MyList再传递给MyItem。

App.vue

<template>
...<!-- 先将函数传递给MyList --><MyList :todos="todos" :checkTodo="checkTodo"></MyList>
...
<script>javascript">// 勾选or取消勾选一个todocheckTodo (id) {this.todos.forEach((todo) => {if (todo.id === id) {todo.done = !todo.done}})}
</script>

MyList.vue

  <MyItem   v-for="toboObj in todos" :key="toboObj.id" :todo="toboObj"  :checkTodo="checkTodo" />
<script>javascript">props: ["todos", "checkTodo"]
</script>

MyItem.vue

javascript">// 接收MyList组件传递的对象
props: ["todo", "checkTodo"],methods: {handleCheck (id) {this.checkTodo(id)}
}

需要注意的是:
:checked="todo.done" ----初始化复选框
@change="handleCheck(todo.id) ----更新复选框
这两个操作可用v-model进行合并

<!-- 这行代码也能实现,但是有点儿违反原则,因为这样修改了props里数据的值,不报错是因为,todo是个对象,地址值没被修改, --> 
<input type="checkbox" v-model="todo.done" />

5. 删除

在这里插入图片描述
点击按钮,获取当前MyItem的id,根据id删除该条数据。同样的套路

添加监听事件,监听事件里调用父组件传递过来的函数。通过父组件里的这个函数对todos进行删除操作。
App.vue:

<MyList :todos="todos" :checkTodo="checkTodo" :deleteTodo="deleteTodo"></MyList>
<script>javascript">// 删除一个tododeleteTodo (id) {this.todos = this.todos.filter((todo) => {return todo.id !== id})}
</script>

MyList.vue:

<MyItem
v-for="toboObj in todos"
:key="toboObj.id"
:todo="toboObj"
:checkTodo="checkTodo"
:deleteTodo="deleteTodo"
/>
<script>javascript">props: ["todos", "checkTodo", "deleteTodo"]
</script>

MyItem.vue:

<button class="btn btn-danger" @click="handleDelete(todo.id)">删除</button>
<script>javascript">handleDelete (id) {// 弹框if (confirm('确定要删除吗?')) {// 通知App,删除对应的todothis.deleteTodo(id)}}
</script>

在这里插入图片描述

6. footer底部统计

在这里插入图片描述

<!--Footer.vue--> 
<!--使用计算属性--> 
<span>已完成{{ doneTotal }}</span> / 全部{{ total }}
<script>javascript">props: ["todos"],computed: {total () {return this.todos.length},doneTotal () {// reduce记数return this.todos.reduce((prev, cur) => {return prev + (cur.done ? 1 : 0)}, 0)// 简写// return this.todos.reduce((prev, current) => prev + (current.done ? 1 : 0))}
</script>

7. footer底部交互

这里结合6底部统计一起看

7.1 全选框自动打勾

如果代办事项全都选上,则该框自动打勾,
在这里插入图片描述

<input type="checkbox" :checked="isAll" @change="checkAll" />
<script>javascript">computed: {isAll () {// 已完成的数量是否等于todos的总数return this.doneTotal === this.total}},
</script>  

但是这样有个问题:
在这里插入图片描述
改进:

javascript">isAll () {return this.doneTotal === this.total && this.total > 0
}

优化:当没有代办事项时,footer组件不应该显示
在这里插入图片描述

7.2 全选框取消勾选

方式一:添加点击事件
App组件中创建操作todos的函数并传递给子组件
在这里插入图片描述
子组件接收函数并调用
在这里插入图片描述
方式二:v-model
(注意此处与 第4节的勾选与取消勾选一个Todo的区别)

<!-- :check = "isAll"用于初始化复选框
@change="checkAll"用来更新复选框
-->
<input type="checkbox" :checked="isAll" @change="checkAll" />
<!-- 简写为 -->
<input type="checkbox" v-model="isAll" />

由于isAll是计算属性,且v-model是双向绑定,所以当操作复选框时,对isAll的值进行了修改;
在这里插入图片描述
所以此时isAll不能采用简写形式了

javascript">isAll: {get () {return this.doneTotal === this.total && this.total > 0},set (value) {this.checkAllTodo(value)}
}

8. 清除已完成任务

在这里插入图片描述

添加点击事件
MyFooter.vue

<button class="btn btn-danger" @click="clearAll">清除已完成任务</button>
<script>javascript">
props: ["todos", "checkAllTodo", "clearAllTodo"],
clearAll () {this.clearAllTodo()
}
</script>

App.vue

<MyFooter:todos="todos":checkAllTodo="checkAllTodo":clearAllTodo="clearAllTodo"
></MyFooter>
<script>javascript">
// 清除所有已完成的todoclearAllTodo () {this.todos = this.todos.filter((todo) => {return !todo.done})}
</script>

总结

  1. 组件化编码流程:
  • 拆分静态组件:组件要按照功能点拆分,命名不要与html元素冲突。
  • 实现动态组件:考虑好数据的存放位置,数据是一个组件在用,还是一些组件在用
    • 一个组件在用:放在组件自身即可。
    • 一些组件在用:放在他们共同的父组件上(状态提升
  • 实现交互:从绑定事件开始。数据在哪里,对数据进行处理的方法就在哪里
  1. props适用于:

    ​ (1).父组件 ==> 子组件 通信

    ​ (2).子组件 ==> 父组件 通信(要求父先给子一个函数)

  2. 使用v-model时要切记:v-model绑定的值不能是props传过来的值,因为props是不可以修改的!

  3. props传过来的若是对象类型的值,修改对象中的属性时Vue不会报错,但不推荐这样做。

项目完整代码链接:https://gitee.com/LXHST/vue2–Todo-list-case-1.0/tree/master/


http://www.ppmy.cn/news/1520759.html

相关文章

虚幻引擎VR游戏开发01 | VR设备和术语

四款Unreal Engine默认配套按键映射的VR设备 IMC按键映射 Oculus Touch (R) Grip Axis: 代表Oculus Rift或Quest设备的右手控制器的抓握轴输入。Valve Index (R) Grip Axis: 代表Valve Index设备的右手控制器的抓握轴输入。Vive (R) Grip: 代表HTC Vive设备的右手控制器的抓握…

力扣452-用最少数量的箭引爆气球(Java详细题解)

题目链接&#xff1a;452. 用最少数量的箭引爆气球 - 力扣&#xff08;LeetCode&#xff09; 前情提要&#xff1a; 因为本人最近都来刷贪心类的题目所以该题就默认用贪心方法来做。 贪心方法&#xff1a;局部最优推出全局最优。 如果一个题你觉得可以用局部最优推出全局最…

web前端-网页

一、网页 1.网页 网站是指在因特网上根据一定的规则&#xff0c;使用 HTML等制作的用于展示特定内容相关的网页集合。 网页是网站中的一“页”&#xff0c;通常是 HTML格式的文件&#xff0c;它要通过浏览器来阅读。 网页是构成网站的基本元素,它通常由图片、链接、文字、声…

RAG 实践- Ollama+RagFlow 部署本地知识库

前言 本文我们介绍另一种实现方式&#xff1a;利用 OllamaRagFlow 来实现&#xff0c;其中 Ollama 中使用的模型仍然是Qwen2 我们再来回顾一下 RAG 常见的应用架构 RagFlow的安装和部署 前置条件 CPU > 4 核RAM > 16 GBDisk > 50 GBDocker > 24.0.0 & Dock…

赛码网牛客在acm模式下利用node.js处理多行输入方法

赛码网在JS Node的语言下&#xff0c;acm模式的默认标准输入输出代码是这样的&#xff1a; const readline require(readline);const rl readline.createInterface({input: process.stdin,output: process.stdout }); rl.on(line, function (line) {const tokens line.spli…

qt配合halcon深度学习网络环境配置

1.开发环境qt6&#xff0c;编译器MSCV2019&#xff0c;网络是halcon的对象检测&#xff0c;halcon用20. 2.建立qt项目 3.到halcon安装目录下复制include,lib这两个文件夹到qt项目中进行引用 4.引用到halcon静态库后&#xff0c;到halcon运行目录下找到静态库对应dll文件&…

Linux之grafana+onealert报警

grafana介绍 Grafana是一个开源的度量分析和可视化工具&#xff0c;可以通过将采集的数据分析&#xff0c;查询&#xff0c;然后进行可视化的展示,并能实现报警。 grafana安装与登录 在grafana服务器上安装grafana 下载地址&#xff1a;https://grafana.com/grafana/downloa…

【QNX+Android虚拟化方案】114 - QNX /dev/switch 节点创建 及 读写功能实现实例

【QNX+Android虚拟化方案】114 - QNX /dev/switch 节点创建 及 读写功能实现实例 一、/dev/switch 节点创建代码分解1. 头文件包含2. 创建节 /dev/switch 节点代码3. /dev/switch 节点读函数实现(cat /dev/switch)4. /dev/switch 节点写函数实现(echo "abcdef" &g…

排序算法:

直接插入排序&#xff1a; 它的工作原理是通过构建有序序列&#xff0c;对于未排序数据&#xff0c;在已排序序列中从前向后或从后向前扫描&#xff0c;找到相应位置并插入。 参考链接&#xff1a;排序算法之插入排序&#xff08;python实现&#xff09;_python插入排序-CSDN…

union 的正确食用方法

0.前情提要 &#xff08;很久&#xff09;之前上编译原理时&#xff0c;一次实验课需要补充完善一个用 c 写的词法分析器&#xff1b;而这个分析器在定义语法树结点时使用了 union 存储语言中不同表达式的类型标签或值本身。因为当时刚好学完了 cpp&#xff0c;拿着锤子看啥都…

SQL典型练习题

with可以解决很多想用子表解决的问题 over可以加想加的&#xff0c;改变表的结构 例题&#xff1a; 表(driver)说明&#xff1a;司机登录登出明细表&#xff0c;由于同一司机有可能同时登录两个司机端&#xff0c;所以同一时间段一个司机有可能会产生两条或者更多条数据。 …

九、安装artifactory并配置PostgreSQL--失败了

八、centos7安装mysql5.7-CSDN博客 基于八&#xff0c;克隆出一个新的虚拟机&#xff0c;用来安装制品库并配置mysql数据库。 比较官方的文章&#xff1a; How to install JFrog Artifactory on CentOS 7 | CentLinux 仅参考&#xff0c;未使用&#xff08;配置的centos自带…

网络压缩之参数量化(parameter quantization)

参数量化&#xff08;parameter quantization&#xff09;。参数量化是说能否只 用比较少的空间来储存一个参数。举个例子&#xff0c;现在存一个参数的时候可能是用64位或32位。 可能不需要这么高的精度&#xff0c;用16或8位就够了。所以参数量化最简单的做法就是&#xff0c…

什么是云计算?

1.云计算的概念&#xff1f; 现阶段广为人们所接受的是美国国家标准与技术研究院&#xff08;National Institute of Standards and Technology&#xff0c;NIST&#xff09;给出的定义&#xff1a;“云计算”是一种按使用量付费的模式&#xff0c;这种模式提供可用的、便捷的、…

Lua:条件断点

如果有很多方式都要经过这个函数&#xff0c;但是你只需要满足其中例如参数等于Test的这一种&#xff0c;可以在断点处右键点击编辑断点打上条件断点&#xff0c;只有参数EventName等于Test的才会断上。

《JavaEE进阶》----4.<SpringMVC①简介、基本操作(各种postman请求)>

本篇博客讲解 MVC思想、及Spring MVC&#xff08;是对MVC思想的一种实现&#xff09;。 Spring MVC的基本操作、学习了六个注解 RestController注解 RequestMappering注解 RequestParam注解 RequestBody注解 PathVariable注解 RequestPart注解 MVC View(视图) 指在应⽤程序中…

★ 算法OJ题 ★ 力扣 LCR179 - 和为 s 的两个数字

Ciallo&#xff5e;(∠・ω< )⌒☆ ~ 今天&#xff0c;小诗歌剧将和大家一起做一道双指针算法题--和为 s 的两个数字~ 目录 一 题目 二 算法解析 三 编写算法 一 题目 LCR 179. 查找总价格为目标值的两个商品 - 力扣&#xff08;LeetCode&#xff09; 二 算法解析 …

NCH DrawPad Pro for Mac/Win:强大的图像编辑处理软件

NCH DrawPad Pro for Mac/Win是一款功能全面的图像编辑和设计软件&#xff0c;专为Mac和Windows用户设计。它不仅适用于专业设计师&#xff0c;也深受业余爱好者和创意工作者的喜爱。DrawPad Pro凭借其丰富的绘图工具、强大的编辑功能和便捷的模板库&#xff0c;为用户提供了卓…

集成电路学习:什么是LCD液晶显示器

一、LCD&#xff1a;液晶显示器 LCD&#xff0c;全称Liquid Crystal Display&#xff0c;即液晶显示器&#xff0c;是一种平面超薄的显示设备。它由一定数量的彩色或黑白像素组成&#xff0c;放置于光源或者反射面前方。LCD的主要原理是以电流刺激液晶分子产生点、线、面配合背…

五,Spring Boot中的 Spring initializr 的使用

五&#xff0c;Spring Boot中的 Spring initializr 的使用 文章目录 五&#xff0c;Spring Boot中的 Spring initializr 的使用1. 方式1&#xff1a;IDEA创建2. 方式2&#xff1a;start.spring.io 创建3. 注意事项和细节4. 最后&#xff1a; 需要&#xff1a;使用 Spring initi…