当前位置: 首页 > news >正文

【Vue】 实现TodoList案例(待办事项)

目录

组件化编码流程(通用)

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

2.展示动态数据:

1. 常规 HTML 属性

3.交互——从绑定事件监听开始

什么时候要用 event:

什么时候不需要用 event:

总结TodoList案例

总结不易!本章节对我有很大的收获, 希望对你也有帮助!!!


本节文件素材自取:https://gitee.com/liu-yihao-hhh/i-love---vue/tree/master/vue-06/src

组件化编码流程(通用)

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

第一步,进行拆分组件!
首先定义好各个组件的名称,然后分别进行引入和注册
App组件
Item组件属于List的子组件,单独进行引入和注册
这里有当前模块化的html和css直接进行引入, 然后通过 自己拆分,来分别引入组件即可!
现在就定义好了一个静态的组件!

2.展示动态数据:

  • 数据的类型、名称是什么?
  • 数据保存在哪个组件?
在MyList中存在一堆待处理的事情的时候,我们肯定就是用数组对象来进行存储,每一个都具有当前标签的id号,内容title和是否完成done
进行渲染的时候,可以用我们之前学到的v-for = " todoObj in todos" 注意绑定:key=“todoObj.id”值
实际上是写成 v-for = "(title, index) in todos"

传入值给MyItem 进行值的接收~ 打印这里的生命周期钩子中todo对象

v-bind就是得到Vue里面的值 然后进行传给html标签里面的属性值使用!

1. 常规 HTML 属性

  • href: 链接的 URL

  • src: 图像、视频或其他资源的来源

  • alt: 图像的替代文本

  • title: 元素的提示信息

  • disabled: 控制按钮、输入框等元素的禁用状态

  • readonly: 使输入框成为只读

  • checked: 复选框或单选框的选中状态

  • value: 表单控件的值

  • placeholder: 表单控件的占位符文本

  • maxlength: 输入框允许的最大字符数

  • type: 表单控件的类型,如 textpasswordcheckbox

就好比 给img :src=“”图片传入地址

    3.交互——从绑定事件监听开始

    在MyHeader.vue中,进行事件添加, 每次按下回车,都会添加一条新的todo任务

    • @keyupv-on:keyup 的简写,它用于监听 keyup 事件。keyup 事件会在用户松开按键时触发。

    • .enter 是一个修饰符,它限制只在用户按下 Enter 键 时触发事件。也就是说,只有当用户按下 Enter 键并松开时,才会触发 add 方法。

    • add 是你在 Vue 组件中定义的方法,当这个事件触发时,Vue 会调用 add 方法。

    这里有两种办法来接受输入框的数据:

    1. 给这个add函数来进行添加

    • event 是触发 keyup 事件时,浏览器传递给事件处理函数的原生 DOM 事件对象。

    • event.target 是触发事件的元素(即 <input> 输入框)。

    • event.target.value 获取的是这个输入框的当前值,也就是用户输入的内容。

    什么时候要用 event

    1. 你需要获取触发事件的元素(比如按钮、输入框等): 比如你点击了一个按钮,想知道是哪个按钮触发了事件,或者想获取这个按钮的某个属性(比如按钮的文本、值等)。这时需要 event.target 来拿到这个元素。

    <button @click="handleClick">Click me</button>methods: {handleClick(event) {console.log(event.target); // 这里你就可以得到触发点击的那个按钮元素}
    }
    

    你需要获取更多的事件信息: 比如你按了某个键,想知道是哪个键被按下。你需要 event.key 来获取按下的键的名字(例如 "Enter""Escape" 等)。

    <input type="text" @keyup="handleKeyup">methods: {handleKeyup(event) {console.log(event.key); // 输出你按下的键名}
    }
    

    你需要阻止事件的默认行为: 比如你点击了一个提交按钮,但你不想让它立即提交表单,而是执行其他的操作。你可以使用 event.preventDefault() 来阻止表单的提交。

    <form @submit="handleSubmit"><button type="submit">Submit</button>
    </form>methods: {handleSubmit(event) {event.preventDefault(); // 阻止表单提交console.log("表单没有提交");}
    }
    

    你需要停止事件冒泡: 有时候你点击某个元素时,可能不希望事件传播到父元素(例如,你点击了按钮,但父元素的点击事件也不想被触发)。这时你可以使用 event.stopPropagation() 来停止事件的传播。

    <div @click="handleDivClick"><button @click="handleClick">Click me</button>
    </div>methods: {handleDivClick() {console.log("Div clicked");},handleClick(event) {event.stopPropagation(); // 阻止事件冒泡,不让父 div 的点击事件触发console.log("Button clicked");}
    }
    

    什么时候不需要event

    • 如果你不需要获取事件的具体信息(比如你只是希望某个方法被执行),就不需要用 event。比如你用 Vue 的 @click,然后直接调用一个方法,没有涉及到原生事件信息的处理时,就不需要传 event

    2. 采用v-modle进行双向数据绑定,来直接获取输入的title值

    v-model="title":实现了输入框的值与 title 数据的双向绑定。

    为了生成一个绝对不会重复的id号, 这里就推荐一个nanoid库进行生成唯一的id

    安装好nanoid库后,直接进行引入:然后打印出输入的对象看看效果!

    由于我们现在数据在MyHeader上 需要将数据传入到MyList内才能将数据进行渲染,但是我们现在实现不了兄弟组件之间的互传,就比如上面之前的List组件传至item组件, 它们之间的关系就是父子组件的关系, List引入了item组件,所以才可以通过props进行传输数据!

    这里我们只能先将header数据传入App 然后 才从App传入至List的方法可行!!!

    1. 先实现比较简单的这条线,将数据从App组件传向List就是用props即可,将todos数组放入App组件,进行传输:

    App组件:

    List获取App组件传来的todos 然后再传给item单个事件进行渲染:

    2.第二条线就是, 要将Header输入框的值传送给App组件!

    然后就只需要将receive名字换成addTodo 并且获得的todoObj进行unshift数组todos即可!

    Header组件进行数据检验!

    if(!event.target.value.trim()) return alert('输入不能为空')

    export default {name: 'MyHeader',props:['addTodo'],methods: {add(event) {// 检验数据if(!event.target.value.trim()) return alert('输入不能为空')// 将用户的输入包装成一个todo对象// console.log(event.target.value)const todoObj = {id:nanoid(), title: event.target.value, done:false}// console.log(todoObj)// 通知App组件添加一个todoObj对象this.addTodo(todoObj)event.target.value = ''}}
    }

    当我想要改变当前标签值的done时, 首先第一步就是要获得该事件的id号!再Item组件中~

    那么仍然再App组件内进行定义函数:来进行勾选或取消勾选当前事件,得到该id后 将当前事件的done进行反转!

    那么就要将该函数进行传递至item组件内, 就要进行连续传递两次

    item勾选or取消勾选的另一种方法!直接利用v-model的双向数据绑定, 来获取props传来的数组todo.done来控制当前的checkbox的勾选效果!

    但是这里有一个很明显的冲突:

    这里的todo.done 是props传进来的 是只读的 但是这里却被修改了

    1.      但是Vue的监测比较宽松,比如:let obj = {a: 1, b: 2}
    2.      obj.a = 666 这种只修改属性值, Vue是监测不到的
    3.      obj = {x: 100, y: 200} 这种修改整个对象 才是Vue能够监测到的

    所以强烈不建议这种写法,还是不要直接对props进行修改的好~

    定义删除item任务, 跟勾选是用养一个效果, 再App组件内进行创建deleteTodo函数 然后进行传递给item组件中!

    Footer计算任务:

    Footer组件要接收App传入的todos 然后来计算当前的全部任务和已完成任务数!

    <span>已完成{{ doneTotal }}</span> / 全部{{ todos.length }}
    export default {name:'MyFooter',props:['todos'],// 计算属性 因为我们要计算已完成的任务数computed: {// 简写 写成函数形式doneTotal() {// 写法不高级// let i = 0// this.todos.forEach(todo => {if(todo.done) i++})// return i// 第一个参数就是一个函数 第二个参数 用来做统计的初始值 就像是定义 i = 0// 数组的长度是几 这个函数就被调用几次// pre 就是上一次的值, current就是当前的值// 返回值就是下一次执行这个函数的pre来进行接收// 最后一次调用函数的返回值就是整个reduce方法的返回值// current就是每一个todo对象 就是数组里面的下标为pre当前内容// const x = this.todos.reduce((pre, current) => {//   return pre + (current.done ? 1 : 0)// }, 0)// return xreturn this.todos.reduce((pre, todo) => pre + (todo.done ? 1 : 0), 0)}}
    }
    

    计算已完成任务数,这里用到了reduce这个数组内置函数,用来进行筛选计算作用,那么就要放入计算函数内部进行返回!

    reduce() 方法对数组中的每个元素按序执行一个提供的 reducer 函数,每一次运行 reducer 会将先前元素的计算结果作为参数传入,最后将其结果汇总为单个返回值。

    全部勾选 or 全部不勾选按钮 以及 清除已经完成的任务

    Footer的input checkbox复选框:

    但是这里input 又采用:checkbox 进行获取isAll的值 还进行@click进行点击事件 所以二者可以进行合并为v-model= "isAll"

    正常流程是: get() → 用户修改 → set(value) → 响应式数据变了 → 自动触发 get() → 页面刷新

    清除已完成任务:

     本节文件素材自取:https://gitee.com/liu-yihao-hhh/i-love---vue/tree/master/vue-06/src

    总结TodoList案例

    1. 组件化编码流程:

      ​ (1).拆分静态组件:组件要按照功能点拆分,命名不要与html元素冲突。

      ​ (2).实现动态组件:考虑好数据的存放位置,数据是一个组件在用,还是一些组件在用:

      ​ 1).一个组件在用:放在组件自身即可。

      ​ 2). 一些组件在用:放在他们共同的父组件上(<span style="color:red">状态提升</span>)。

      ​ (3).实现交互:从绑定事件开始。

    2. props适用于:

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

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

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

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

    总结不易!本章节对我有很大的收获, 希望对你也有帮助!!!

    http://www.xdnf.cn/news/219961.html

    相关文章:

  • Java高频面试之并发编程-10
  • C++之string
  • 如何在本地部署小智服务器:从源码到全模块运行的详细步骤
  • CA校验主辅小区配置及UE能力
  • 首发记忆行车方案与座舱智能管家,佑驾创新“抢跑”驾舱融合市场
  • 恒流恒压直流充电测试负载设计:构建精准化检测体系
  • 计算机基础:二进制基础14,二进制加法
  • 如何将二叉树展开为链表?两种Java实现方法对比
  • FPGA 38 ,FPGA 网络通信协议栈基础,ARP 协议深度解析与模块划分( ARP与以太网帧,以及ARP模块常用文件 )
  • 细说STM32单片机FreeRTOS互斥量及其编程实例
  • C# 导入EXCEL 报错外部表不是预期的格式错误指南方案
  • C++中的vector和list有什么区别?
  • Launcher3-实现家长管控-儿童模式-老人模式
  • 机器学习第四篇 线性回归-最小二乘法
  • 案例分享|20倍提效!水力设备电磁仿真的云端实战
  • DDoS攻击真的无解吗?
  • DeepClaude开源程序可以实现代码生成、创作诗句以及内容创作等功能
  • 详解大语言模型生态系统概念:lama,llama.cpp,HuggingFace 模型 ,GGUF,MLX,lm-studio,ollama这都是什么?
  • 【LaTex】3.8流程图绘制
  • Transformer数学推导——Q34 推导位置插值(Position Interpolation)在长文本外推中的误差上界
  • (02)Redis 的订阅发布Pub/Sub
  • Ubuntu上搭建python环境并安装第三方库
  • C语言教程(二十四):C 语言中递归的详解
  • cuda学习3: 全局线程id计算
  • 大语言模型能否替代心理治疗师的深度拓展研究:fou
  • 两数之和II-输入有序数组(中等)
  • 洛谷题解 | CF1979C Earning on Bets
  • DNA复制过程3D动画教学工具
  • 稳定性 复杂度
  • 浅析localhost、127.0.0.1 和 0.0.0.0的区别