用vue.js写案例——ToDoList待办事项 (步骤和全码解析)

 

目录

 

一.准备工作

二.编写各个组件的页面结构

三.实现初始任务列表的渲染

四.新增任务

五.删除任务

六.展示未完成条数

七.切换状态-筛选数据

八.待办事项(全)代码


 

一.准备工作

在开发“ToDoList”案例之前,需要先完成一些准备工作,包括创建项目、引入 BootStrap 样式文件和搭建基本项目结构,下面分别进行实现。

(1)创建项目 创建项目包含新建项目、安装依赖项和运行项目,具体步骤如下。

① 创建项目。使用HbuliderX软件创建todolist项目 在src的目录下创建style.css 文件中的样式,具体代码如下。

style.css样式如下:

:root {
 
font-size: 16px;
 }
 body {
 
 margin: 0;
 }

② 新建并封装组件。在D:\vue\chapter03\todolist\src\components 目录下新建文件 ToDoHeader.vue、ToDoMain.vue 和 ToDoFooter.vue,分别表示 ToDoHeader、ToDoMain 和ToDoFooter 组件。

8e63932db2404753a837df16d181551d.png

③ 各个组件中的<style>节点的样式代码。

二.编写各个组件的页面结构

 

准备工作完成之后,接下来编写各个组件的页面结构,实现“ToDoList”案例静态页 面的渲染,具体步骤如下。

①在App组件中以局部注册的方式引入ToDoHeader、ToDoMain、ToDoFooter组 件

c3c81311e10c46ed8d4af3506e13323d.png

 ②在ToDoHeader组件中编写输入区域的页面结构

fa84afc733e6431191418e97f8e7b921.png

③ 在ToDoMain组件中编写列表区域的页面结构

d454f098d65d42879f1d913ac89dfaec.png

④ 在ToDoFooter组件中编写切换状态区域的页面结构

b4b2759ee9d34cfa9d07b7793531242c.png

三.实现初始任务列表的渲染

App 组件为根组件,数据在App组件中,现在需要将App根组件中的初始数据传递 到列表区域,ToDoMain组件中。即通过props(自定义属性)从父组件(App组件)向 子组件(ToDoMain组件)中传递数据。实现初始任务列表具体步骤如下。

① 在ToDoMain组件中定义可以从父组件中接收的数据

a31c454f08a842e1b18202f2846a1372.png

② 在App组件中定义页面的初始数据

125df32731374900b29c74a6803b1f8c.png

③ 通过自定义属性进行传递数据

47d152b81ad44c828177e4a41b85b208.png

④ 修改ToDoMain组件中的代码,将接收到的list数据进行展示。

c19b82dddc644fd28dfb1f4b3b5f775a.png

四.新增任务

“ToDoList”案例中在文本框中输入内容,按下回车后添加任务到任务列表,将用户 输入的任务名称通过自定义事件从ToDoHeader组件传递到App组件,具体步骤如下代码省略。、

① 修改ToDoHeader组件中的代码,添加页面的初始数据

6d477c062f894cdbbfb74230af780d7f.png

② 获取input输入框的值,修改ToDoHeader组件中的代码

e2f978b70c79453da8e14bc6880a4835.png

③ 修改ToDoHeader组件中的代码,为input输入框绑定回车事件,事件处理函数 名称为enterName

ad84ce526bed4199a8dcb8f571cc04c7.png

④ 修改ToDoHeader组件中的代码,通过调用defineEmits()方法来声明自定义事 件

c51b6c2960c146818afafc7959fb5a75.png

⑤ 在ToDoHeader组件中添加enterName()方法,通过调用emit()方法触发自定义事 件

db2bdeb5191f415a84bfdba34e1c07f9.png

⑥ 在App组件中监听addTodo自定义事件,当enterName事件触发时,调用 addToDo()方法

a9daf96d031d41678b31b2bd14c00741.png

⑦ 添加addToDo方法,实现数据的处理

ace429f781b54af6bfbf7bcd8b9ec848.png

 

五.删除任务

当鼠标指针滑到任务列表中每一项时,在右侧会出现“×”图标,单击该图标即可 进行删除当条任务操作。首先在ToDoMain组件中声明并触发自定义事件,传递参数 6 id,接着在App组件中监听自定义事件,当自定义事件被触发时,执行对应的方法,进 行删除操作,删除任务的具体实现步骤如下。

① 在ToDoMain组件中,声明自定义事件delTodo,用于表示删除任务

5d51e85dcec5496a8a303f7a5bc1487b.png

② 在ToDoMain组件中定义delToDo()方法,触发自定义事件

716fdb98ccb34973b645bb753a6a2951.png

③ 修改删除按钮的代码,添加点击事件,传入需要删除的id

c76f6242dd4149dca4fc6d338dc9960d.png

④ 在App组件中监听

8f6d8267e865479199613869cb1903a9.png

⑤ 在App组件中添加delToDo方法,进行列表中对应任务的删除操作

fa36dffbcd6c49bdaf6039b2037e4f6f.png

六.展示未完成条数

在任务状态区域的左侧会显示未完成任务的条数,接下来计算未完成任务的条数并 将其在页面中渲染出来,具体步骤如下代码省略。

① 在App组件中定义计算属性,计算未完成的任务条数

2f144a08ee2c4ef28d79cf9d9ae16d80.png

 ② 将自定义属性传给ToDoFooter组件

d383da5dd7ca4859afd92edf7556bdd7.png

③ 在ToDoFooter组件中接收lastLength

59df8f2739cb4906b48915600a70e5ba.png

④ 在ToDoFooter组件中将条数展示出来

34c37fc1d76241449ee53761ec7aa81b.png

七.切换状态-筛选数据

单击切换状态区域时,默认状态为all,即显示全部任务,当状态切换为active时, 显示未完成的任务,当状态切换为completed时,显示已完成的任务,实现切换数据筛选 状态具体步骤如下代码省略。

① 首先在App组件中定义页面的使用一个任务状态状态属性status

8f854ba8fe7347eeb9aaaea69fda5b23.png

② 在App组件中通过不同的status展示不同的任务,实现任务数据的切换

d95eae8d69894ceb99decc19e70aea6e.png

③ 修改App组件,将showList传递给ToDoMain组件

f1b9a881a1b64f40b627ee1607e4849b.png

④ 设置自定义事件名称

c8834c8f03bc48629a187fe342700e35.png

⑤ 在ToDoFooter组件中定义props属性,表示从父组件中接收该数据

412a9b294236430aa57ba154e445b965.png

⑥ 在App组件中定义props,即从App组件中传递status到ToDoFooter组件中

cf37bcebc9604fdc98f334389fef354c.png

⑦ 在ToDoFooter组件中单击链接按钮时更改状态

6305a1604ccb407ba09d326aad030eb6.png

⑧ 在App组件中监听updateStatus自定义事件,通过自定义事件将status属性的值 从ToDoFooter组件传递到App组件中,具体代码如下

135af15de1264610997e645b41e0cd59.png

⑨ 定义updateStatus()方法,用来更新状态,具体代码如下。

b3e781afc384481e97d09d50c72f1102.png 

八.待办事项(全)代码

d1d6f8abbd6c4e7b8face81024650a43.png

ToDoFooter.vue代码:

<template>
	<div class="footer">
	<span class="todo-count">共<strong>{{ lastLength }}</strong>条未完成任务
	</span>
	 <ul class="filters">
	   <li>
	  <a @click.prevent="emit('updateStatus', 'completed')" :class="{ selected: status === 'completed' }"
	  href="#/completed" style="background-color: lightblue;">Completed</a>
	  </li>
	 <li>
	  <a @click.prevent="emit('updateStatus', 'active')" :class="{ selected: status === 'active' }"
	  href="#/active" style="background-color: lightblue;">Active</a>
	  </li>
	 <li>
	  <a @click.prevent="emit('updateStatus', 'all')" :class="{ selected: 
	 status === 'all' }" href="#/" style="background-color: lightblue;">All</a>
	  </li>
	  </ul>
	 </div>
</template>

<script setup>
	const props = defineProps(['lastLength','status'])
	

</script>

<style>
		
	.filters{
		display:flex;
		flex-direction:row-reverse;/* 相反方向 */
	}
	ul{
		list-style: none;
	}
	ul li{
		padding-left:10px ;
	}
	a{
		text-decoration: none;
		border: 1px solid black;
		color: black;
	}
</style>

ToDoHeader.vue代码: 

<template>
	<div>
	 
	 <div class="header">
	 
	<p class="title">待办事项</p>
	 
	 <input class="new-todo" type="text" placeholder="请填写任务" v-model.trim="name"  @keyup.enter="enterName" />
	 
	 </div>
	 
	</div>
	
</template>

<script setup>
	import { ref } from 'vue'
	 const name = ref('')
	  const enterName = () => {
	  emit('addTodo', name.value)
	  name.value = ''
	  }
	  const emit = defineEmits(['addTodo'])

</script>

<style>
	.title{
		border-bottom:1px solid grey;
		text-align:center;
		font-size:36px;
		color:brown;
	}
	.header{
		border:1px solid grey;
	}
	
	.new-todo{
		position: relative;
		top:-20px;
		left: 50px;
		border: none;
		font-size: 20px;
	}
	
</style>

 ToDoMain.vue代码:

<template>
	<div class="main">
	 <ul class="todo-list">
	 <li v-for="item in list" :key="item.id" :class="{ completed: item.done }">
	  <div class="view">
	  <input class="toggle" type="radio" v-model="item.done" />
	  <label class="zi">{{ item.name }}</label>
	  <button class="destroy" @click="delTodo(item.id)"></button>
	  </div>
	  
	  </li>
	 </ul>
	 
	 </div>
	 
</template>

<script setup>
	const props = defineProps({
			list: {
				type: Array,
				required: true
			},
			})
	const emit = defineEmits(['delTodo'])
  const delTodo = id => {
  id && emit('delToDo', id) // 触发事件
  }
</script>

<style>
.toggle{
	width: 30px;
	height: 30px;

}
.view{

margin-left: -40px;	
}
.zi{
	font-size: 18px;
   padding-left: 20px;

}
.destroy{
	border: none;
	margin-left: 10px;
}
</style>

App.vue代码:


<script setup>
// This starter template is using Vue 3 <script setup> SFCs
// Check out https://v3.vuejs.org/api/sfc-script-setup.html#sfc-script-setup
import ToDoHeader from './components/ToDoHeader.vue'
import ToDoMain from './components/ToDoMain.vue'
import ToDoFooter from './components/ToDoFooter.vue'
import { ref, computed, defineEmits } from 'vue'

const emits = defineEmits(['updateStatus']) // 添加 defineEmits 声明

const status = ref('all')
const list = ref([
  { id: 1, name: '晨练', done: false },
  { id: 2, name: '练书法', done: true },
  {id:3,name:'完成Vue.js组件部分习题',done:false},
])

const addTodo = (name) => {
  list.value.push({ name, done: false, id: ~~(Math.random() * 1000) })
}

const delToDo = id => {
  list.value = list.value.filter((item) => item.id !== id)
}

const lastLength = computed(() => {
  return list.value.filter((item) => !item.done).length
})

const showList = computed(() => {
  if (status.value === 'all') {
    return list.value
  }
  if (status.value === 'active') {
    return list.value.filter((item) => !item.done)
  }
  if (status.value === 'completed') {
    return list.value.filter((item) => item.done)
  }
})

const updateStatus = (newStatus) => {
  status.value = newStatus;
}
</script>

<template>
 <ToDoHeader @addTodo="addTodo"></ToDoHeader>
  <!-- <ToDoMain :list="showList" @delToDo="delToDo"></ToDoMain> -->
  <ToDoMain :list="list" @delToDo="delToDo"></ToDoMain>
  <ToDoFooter :lastLength="lastLength" :status="status" @updateStatus="updateStatus"></ToDoFooter>
</template>

<style>
	

</style>

 

main.js代码:

import { createApp } from 'vue'
import App from './App.vue'
createApp(App).mount('#app')

 最终效果图如下:

2582c94fd96e48b69449147ae380950a.png

 功能展示:

0b150a6ed583433d96aac86e66d0173a.png今天就分享到此,感谢预览~ 

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/528137.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【AOP入门案例深解析】

AOP 1.AOP简介 AOP&#xff08;Aspect Oriented Programming&#xff09;面向切面编程&#xff0c;是一种编程范式&#xff0c;指导开发者如何组织程序结构 OOP&#xff08;Object Oriented Programming&#xff09;面向对象编程 作用&#xff1a;在步惊动原始设计的基础上进行…

蓝桥杯-AT24C02

1.概述 2.管脚 A1-A3接地 WP保护接地 代码实现 void EEPROM_Write(unsigned char*EEPROM_String,unsigned char addr,unsigned char num) {I2CStart();I2CSendByte(0xA0);I2CWaitAck();I2CSendByte(addr);I2CWaitAck();while(num--){I2CSendByte(*EEPROM_String);I2CWaitAck()…

高等数学基础篇之关于圆,椭圆,圆环的应用

文章目录 前言 1.圆 1.1标准方程 1.2偏心圆 1.3参数方程 2.椭圆 2.1标准方程 2.2参数方程 2.3极坐标 3.圆环 4.扇形 前言 这篇文章主要是应对二重积分出现的一些关于圆的积分域&#xff0c;让大家大概了解一下&#xff0c;不是很详细&#xff0c;因为二重积分对几何…

软件的测试过程模型_v模型

V模型 作用&#xff1a; 主要描述测试、开发之间的对应关系 V模型优点 每个阶段比较清楚&#xff0c;测试过程由底层&#xff08;代码&#xff09;测试到高层&#xff08;应用&#xff09;测试过程 V模型缺点 不适用于需求的变更&#xff0c;发现问题的时机比较晚

基于springboot实现在线教育平台系统项目【项目源码+论文说明】计算机毕业设计

基于springboot实现在线教育平台系统演示 摘要 随着信息技术在管理上越来越深入而广泛的应用&#xff0c;管理信息系统的实施在技术上已逐步成熟。本文介绍了微服务在线教育系统的开发全过程。通过分析微服务在线教育系统管理的不足&#xff0c;创建了一个计算机管理微服务在线…

Golang 基于共享变量的并发锁

一、互斥锁 先看一个并发情况&#xff0c;同时操作一个全局变量&#xff0c;如果没有锁会怎么样 假设有1000个goroutines并发进行银行余额的扣除&#xff0c;每次都扣除10元&#xff0c;起始的总余额是10000&#xff0c;理论上并发执行完应该是0对不对&#xff0c;但实际却不…

C11 lambda、线程库、包装器

目录 一、lambda表达式 1、产生背景 2、使用方法 3、使用lambda解决排序问题 4、组合捕捉 5、捕获外部变量的应用 6、lambda与函数对象 二、线程库 1、thread类 使用方法 2、线程函数参数 3、mutex的种类 std::mutex std::recursive_mutex&#xff1a; std::ti…

Linux中磁盘管理

一.磁盘管理的概括和简要说明 磁盘空间的管理&#xff0c;使用硬盘三步&#xff1a; &#xff08;1&#xff09;分区&#xff1a; &#xff08;2&#xff09;安装文件系统格式化 &#xff08;3&#xff09;挂载&#xff1a; 硬盘的分类&#xff1a; &#xff08;1&#x…

template—模板初阶(C++)

本篇将会对 Cpp 中的模板进行一个简单的介绍&#xff08;后序还关系模板进阶&#xff0c;对模板的内容进行更深入的讲解&#xff09;&#xff0c;其中包括模板的使用&#xff1a;函数模板、类模板&#xff0c;以及对于泛型编程的理解。其中的重点为函数模板&#xff0c;介绍了函…

使用Docker部署jar包

vi DockerfileDockerfile内容 FROM java:8 ADD chery5G-admin.jar chery5G-admin.jar ENTRYPOINT ["java","-jar","chery5G-admin.jar"]上传jar包到Dockerfile文件同级目录 使用Dockerfile文件&#xff0c;将jar包制作为镜像 docker build -t…

04矩阵键盘实现计算器操作

需求:矩阵键盘实现计算器操作 main.c 代码如下: #include <STC89C5XRC.H> #include "ApplicationProgram.h" #include "Int_DigitalTube.h" #include "Int_MatrixKeyboard.h"void main() {u8 KeyPress;App_Initialize();while (1) {Ke…

外贸企业版本自适应通用型外贸英文多语言网站

外贸网站模板&#xff1a;自适应通用型大气外贸英文多语言网站主要是以文字内容为主导&#xff0c;将页面的设计杂乱的图片和元素进行最小化或者去除&#xff0c;从而使整个页面更加简洁、清晰&#xff0c;突出信息的呈现。 下面介绍一下外贸网站模板: 自适应通用型大气外贸英…

第46期 | GPTSecurity周报

GPTSecurity是一个涵盖了前沿学术研究和实践经验分享的社区&#xff0c;集成了生成预训练Transformer&#xff08;GPT&#xff09;、人工智能生成内容&#xff08;AIGC&#xff09;以及大语言模型&#xff08;LLM&#xff09;等安全领域应用的知识。在这里&#xff0c;您可以找…

如何使用群晖Synology Drive结合cpolar内网穿透实现同步Obsidian笔记文件

文章目录 一、简介软件特色演示&#xff1a; 二、使用免费群晖虚拟机搭建群晖Synology Drive服务&#xff0c;实现局域网同步1 安装并设置Synology Drive套件2 局域网内同步文件测试 三、内网穿透群晖Synology Drive&#xff0c;实现异地多端同步Windows 安装 Cpolar步骤&#…

无人机倾斜摄影技术在智慧城市中的应用

随着智慧城市的不断发展和完善&#xff0c;新兴热门技术也不断崛起。无人机技术作为其中之一&#xff0c;具有操作简单、应用灵活等优势&#xff0c;受到了各个行业的青睐。现阶段&#xff0c;无人机技术与5G移动通信系统、人工智能系统深度融合&#xff0c;实现了无人机技术的…

启明智显M系列--工业级HMI芯片选型表

本章主要介绍启明智显M系列HMI主控芯片&#xff1a; 纯国产自主&#xff0c; RISC-V 内核&#xff0c;配备强大的 2D 图形加速处理器、PNG/JPEG 解码引擎、H.264解码&#xff1b;工业宽温&#xff0c;提供全开源SDK&#xff1b;1秒快速开机启动的特性&#xff0c;极大地提高了…

数据结构——双向循环链表

目录 前言 一、链表的分类 二、双向循环链表 2.1 开辟新的节点 2.2 链表初始化 2.3 打印链表 2.4 链表的尾插 2.5 链表的头插 2.6 链表的尾删 2.7 链表的头删 2.8 查找链表 2.9 在pos位置之后插入数据 2.10 删除pos位置的数据 三、完整代码实现 四、顺序表和双向…

使用 R.swift(生成不了R.generated.swift)

今天算是正儿八经创建第一个swift工程&#xff0c;照着视频引用R.swift pod R.swift 工程配置 "$PODS_ROOT/R.swift/rswift" generate "$SRCROOT/R.generated.swift" $TEMP_DIR/rswift-lastrun $SRCROOT/R.generated.swift * 注意 Run角本要放在 Che…

半导体的主要四大应用

半导体是现代信息社会的基石&#xff0c;是现代工业的“粮食”&#xff0c;是电子设备产品生产制造的核心&#xff0c;它与我们的生活紧密相关。涉及到方方面面&#xff0c;半导体芯片、智能汽车、智慧电网、5G通信、航空航天、国防军工、医疗卫生等等。半导体的主要应用都有哪…