尚硅谷vue2的todolist案例解析,基本概括了vue2所有知识点,结尾有具体代码,复制粘贴学习即可

脚手架搭建

1-初始化脚手架(全局安装)

npm install -g @vue/cli

2-切换到创建项目的空目录下

vue create xxxx

整体结构

整体思路

App定义所有回调方法 增删改查 还有统一存放最终数据,所有子组件不拿数据,由App下发数据,类似于数据中心

打个比方,所有子组件只是个可以反复利用的壳子,类似于高达积木,而正在要来拼接他们的是我们的APP组件,有大脑想法,可以决定怎么拼好看,且怎么上色也就是怎么赋予数据得当

当然下放数据可以给其第二个大脑List

第二个数据中心为App给List传的数据todos,其遍历出来的每一个todo下发每一个Item组件,也就是在Item组件里v-for,该item里面的数据隔离开其他数据,可以进行编辑,你也可也在一个List页面同时写了ul,li,此时遍历出来的每个li如果要控制他们单独编辑状态还必须v-if=“showInput&&currRow=i” 来把所有的input同时遍历出来,然后当点击了按钮后传currRow当前编辑行设置为第几个i,然后showInput变为true,

删除操作就传递id然后触发事件遍历过滤出去就行

所有子组件触发的事件 App全部监听 事件可以通过pubsub消息订阅,事件总线,子父组件事件触发和监听方法实现, 父给子传递数据就使用 <sonComponent :子组件里的props接收名=“父组件的数据字段名”> 也可以传递一个方法。子组件props:[‘数据名’]接收

依赖安装

第三方的依赖引入import放在最上面

名称作用使用场合
nanoid生成唯一的Id,防止id冲突不用手动递增ID
pubsub消息订阅与发布孙组件给爷组件传递数据时

依赖用法

nanoid

 npm i nanoidimport { nanoid } from "nanoid";nanoid()

pubsub

npm i pubsub
import pubsub from 'pubsub-js'

父组件挂载时订阅,销毁时取消订阅

  mounted() {this.pubId = pubsub.subscribe('deleteTodo', this.deleteTodo)},beforeDestroy() {pubsub.unsubscribe(this.pubId)},

子组件传递数据,

      //删除handlerDelete(id){if (confirm('确定要删除吗?')) {pubsub.publish('deleteTodo',id)}

注意事项

当你发现一个组件很难命名的时候,可能该组件包含了多个功能,需要更细致的拆分组件

例如Header用来输入信息,List用来展示,编辑,删除操作,这两个就必须拆分开

h5自身有header,head组件,不能起和这俩一样的名字,会有警告,可以在前面加个前缀或直接叫Top还是别的名字

要求

孙组件与父组件通信时使用全局事件总线和消息订阅与发布

update和check使用全局事件总线

deleteTodo使用消息订阅与发布

命名要求

组件

MyHeader
列表MyList
每一个itemMyItem
页脚MyFooter

方法

添加addTodo/handleAdd
勾选checkTodo/handleCheck/checkAllTodo
编辑updateEdit/handleEdit
删除deleteTodo/deleteAllTodo/handleDelete
全选checkAllTodo

数据

所有todotodos
单个todotodo
编辑状态isEdit
是否全选isAll
完成状态done
todo标题title
todoIdtodoId
todo对象todoObj
已完成doneTotal
所有total

涉及的操作 主要内容

$event

传递原生事件,属性target获取触发该事件的DOM对象,DOM对象的value获取其值,用于输入框失焦所触发事件获取输入框值

本地存储+watch深度监视

搭配watch监听器,监听某个数据对象,深度监视为真,表示监视该对象属性

内部设置handler处理函数当数据发生变化时触发,接收两值分别为,newVal变化后值、oldVal变化前值

 watch: {todos: {deep: true,handler(value) {localStorage.setItem('todos', JSON.stringify(value))}}}

只需要第一个newVal,该值为todos对象,由于localStorage存储必须为JSON字符串不能为js对象,需要先转,且取值的时候需要从json字符串转为js对象

localStorage.setItem('todos', JSON.stringify(value))

钩子函数/全局事件总线/ref命名/vue原型

vue实例创建前,给vm原型绑定一个全局变量bus,值为vm本身,这样后续所有父组件可以在bus上监听,子组件在上面触发

$bus.on监听(‘事件名’,回调)

$bus.emit触发(‘事件名’,参数)

打个比方,on相当于耳朵在听,听到了就根据听到的内容做出对应的动作,也就是回调

而emit相当于说,说给耳朵听, 之前单纯的emit只能在父子组件通信,现在引入了一个传话的,隔代通信,事件名相当于一个人名,和谁通信的标识,当然这个on必须在挂载后执行类似于父组件监听子组件的 <Son @Event=回调 />

当然,该传话人必须让所有组件都能看到,访问到,往VueComponent.protoType身上放?每一个标签都会由Vue.extend生成一个新的VueComponent,这样所有组件都能看到this.$bus了?

image-20240624142833094

以下的VueComponent简写成vc,vue实例对象简写成vm (viewModule命名来源于Model-View-ViewModule)

MVVM扫盲:

Module——数据

View——视图(div,input,span…)

ViewModule——方法(视图通过方法来获取到数据的途径, 视图数据间的桥梁)

但是该vc是vue实例对象也就是vm.extend后才有的。一开始没有的,所以该绑定无效,当然你也可以直接改源码,每次extend生成的VueComponent都有该共同传话人(不建议)

可以将其放置在vc的缔造者,vm身上 this。。如果子组件身上的this里没有bus属性则找vm的this,类似于java里的extend继承父类,父类vm有的所有属性子类都有这样就能通过this.$bus.on/emit调用,思路有了。该如何写呢?这里先插入解释一下之前 父子通信的过程

上面听不懂的你就这样记。我们在找一个大家都能 看到的人,委托他帮忙传话,
举个例子, 你要和校长聊天,但是没校长联系方式。你这个时候得找你们班主任 转达你要说的内容给校长,而校长要和你聊天,他也得通过班主任

image-20240624145314436
image-20240624143557840
这里的原型对象和java里的类相似,而实例对象等于类似于java里new出来的实例对象
知道了 o n , e m i t , o f f 在原型对象上了之后且,原型对象 v c 和 v m 都能看到,那问题就好办了,挑一个 v c > 还是 v m 设置为 on,emit,off在原型对象上了之后且,原型对象vc和vm都能看到,那问题就好办了,挑一个vc>还是vm设置为 on,emit,off在原型对象上了之后且,原型对象vcvm都能看到,那问题就好办了,挑一个vc>还是vm设置为bus的属性即可

第一种vc,(好像有点麻烦)


第二种vm

image-20240624152300766
总结一句话, 在原型上的bus属性放置了 vm自身(携带方法on emit off) 所有组件可以通过this. b u s . bus. bus.on 通信

为什么叫$bus? 而不是随便起一个x还是什么乱七八糟的名字。bus翻译过来有总线的意思 而this为全局, 所以称全局事件总线

$ 符号意为 规范用法 vue原型身上的api都用 $ 例如import request from axios.js |||| Vue.prototype.$request=request等等…

插入一句话——————

父组件这样@事件名=回调其实等同于在子组件里 this. $ on(‘事件名’,回调) 监听, ,子组件里this. $ emit触发…都是在同一个VC下使用原型的 $ on emit属性(当然还有一个解除绑定this.$off)所以父子可以通信

当然子组件监听子组件触发 不是有点废话?一般用于同级组件也称兄弟组件,先ref组件命名再指定哪个组件进行监听on,on需在mounted挂载之后执行

image-20240624153935379

image-20240624153911998

注意
on不能重名,可以将其分模块到一个文件下统一constant常量

$ on 销毁前需 $ off 掉 为什么?因为当子组件销毁时 不会自动取消父组件的订阅,你还隔这占着 $ bus傀儡中间人,数量一多,整个vue服务器容易性能下降,好比数据库不使用连接池,你连接多了不用又不释放,占用资源,时间长卡顿甚至数据库崩溃,那为什么vc不用off?,因为vc关闭事件也跟着没,而这里的事件监听on是在 原型上的,一直存在的不受vc关闭而关闭

beforeCreate() {
Vue.prototype.$bus = this
},
image-20240624140051368

挂载后**mounted**,订阅消息,事件总线监听

image-20240625100416758

销毁前**beforeDestroy**,关闭所有订阅,和事件总线监听

image-20240625100423771

至此,我们可以再任意组件之间通信

父子组件传值(数据/方法)

image-20240624154948689

:子组件内部值, =号右边为 父组件自身数据

image-20240624155045577

也可以通过插槽

image-20240624160055792

image-20240624160043944

子< slot name=“body” :rows=“data”> :传递出去的数据名=自身组件数据名

父 < template v-slot:body=“scope”> 子组件所有:传出去的数据为一个对象,父组件使用scope统一接收 例如使用row数据则scope.row

该例子为具名插槽,如果没有name,则使用v-slot:default= 默认插槽,也可以直接写成v-slot=“” v-slot:body 可以简写为#body

element ui的table使用到了该原理, 先给table 绑定数据 :data=xxx 再通过template v-slot="scope.row"获取 当前行的数据

filter过滤删除,foreach循环设置状态

页脚计算属性统计完成数量和总数

全选框根据isAll 中get属性计算返回 《total和done是否相等,且total>0 》 不然total 为0,done也为0也全选了

set属性 意味着每次isAll变化都会传进来复选框的布尔值,以此改变所有的todo.done为true/false

total 计算todo.length

doneTotal计算所有 done为真的 使用todos.reduce累加方法,传递两个形参,第一个为回调函数,接收两个形参pre积累的值,遍历出来的每一个todo, 方法体为 pre+ done? 1:0 ,第二个值为pre的初始值
image-20240624164750106

下划线占位符_

当消息订阅触发的回调函数传来两个参数第一个是消息是名称,第二个是消息传递过来的参数,这时候我们可以选中使用一个XXX占用第一个形参但是会变灰,且提示unuse,也可以使用 占位符,会发光且不提示错误信息

blur 输入框失焦

传递todo,和event事件获取输入框的值,和todo id进行更新对应的todo的title

confirm确认

对象的封装传递 add

单个复选框的change绑定事件

传id,触发事件 遍历勾选Done值

编辑 nextTick/$set /hasOwnProperty/event

input

与title同样位置来一个input 标签绑定数据为 todo.title,v-show与 title互斥 一个为!xxx / 一个为xxx

isEdit属性

给todo追加一个属性isEdit,但是直接给对象添加属性,该属性不是响应式的没有get/set,vue不认可, 模板不会解析(开发遇到的各种问题)

添加响应式属性使用this.$set(todo,‘属性名’,初始值)

二次点击编辑按钮

下一次编辑的时候做判断有了isEdit属性就直接变为true即可,没有的话就set设置属性

判断todo.hasOwnProperty(‘isEdit’) 不能直接判断todo.isEdit 因为有属性但是为false永远不会走if为真的路线

编辑时编辑按钮不显示

编辑状态时编辑按钮不显示. v-show=!isEdit
提交编辑

传递todo id和输入框的值,接用event事件,当失焦时修改, 修改时判断值是否为空!xxx return alert… 成功后isEdit为false

获取焦点

input起名ref=‘名字’, handlerEdit里this.$ref.名字.focus()但是 当点击编辑后他会执行完方法再去渲染视图,导致视图还没出来就聚焦了,聚焦失败,可以使用一个定时器,类似于异步操作,先渲染,然后等一会再聚焦 ,不过官方考虑到了这一点,提供了一个API

this.$nextTick (回调函数),作用是解析完前面代码影响的模板视图再来 执行该函数

image-20240624174516443
官方解释

语法: this.$nextTick(回调)

作用: 下一次DOM更新完执行(上述代码影响后要渲染的DOM)

时机: 需要基于渲染后的DOM进行数据操作时, 例如上述的先要等input出来在聚焦的操作

计算属性的get/set

写成一个对象 内有get/set方法 get来计算值,set来设置值,例如每次复选框的变化 就会触发set,形参为复选框的布尔值

foreach没有返回值,默认为undefined

具体代码 (无样式版)

MyHeader

<template><div><input v-model="inputTitle" placeholder="输入完回车确认" @keyup.enter="handleAdd"/></div>
</template><script>
import {nanoid} from "nanoid";export default {name: "MyHeader",data() {return {inputTitle: ''}},methods: {handleAdd() {if (!this.inputTitle.trim()) return alert('输入不能为空')const todoObj = {id: nanoid(),title: this.inputTitle,done: false}this.$emit('addTodo', todoObj)this.inputTitle = ''}}
}
</script><style scoped></style>

MyList

<template><div><ul><MyItem v-for="todoObj in todos":key="todoObj.id":todo="todoObj"></MyItem></ul></div>
</template><script>
import MyItem from "@/components/MyItem.vue";export default {name: "MyList",props: ['todos'],components: {MyItem}}
</script><style scoped></style>

MyItem

<template><div><ul><MyItem v-for="todoObj in todos":key="todoObj.id":todo="todoObj"></MyItem></ul></div>
</template><script>
import MyItem from "@/components/MyItem.vue";export default {name: "MyList",props: ['todos'],components: {MyItem}}
</script><style scoped></style>

MyFooter

<template><div><ul><MyItem v-for="todoObj in todos":key="todoObj.id":todo="todoObj"></MyItem></ul></div>
</template><script>
import MyItem from "@/components/MyItem.vue";export default {name: "MyList",props: ['todos'],components: {MyItem}}
</script><style scoped></style>

main.js

import Vue from 'vue'
import App from './App.vue'Vue.config.productionTip = falsenew Vue({render: h => h(App),beforeCreate() {Vue.prototype.$bus=this}
}).$mount('#app')

App.vue

<template><div id="app"><MyHeader @addTodo="addTodo"/><MyList :todos="todos"/><MyFooter :todos="todos"@checkAllTodo="checkAllTodo" @deleteAllTodo="deleteAllTodo"/></div>
</template><script>
import MyHeader from "@/components/MyHeader.vue";
import MyList from "@/components/MyList.vue";
import MyFooter from "@/components/MyFooter.vue";
import pubsub from "pubsub-js";export default {name: 'App',components: {MyHeader, MyList, MyFooter},data() {return {//如果 本地存储有数据则使用。没有则初始化空数组,防止reduce计算属性找不到todos.lengthtodos: JSON.parse(localStorage.getItem('todos')) || []}},watch: {todos: {deep: true,handler(newValue) {localStorage.setItem('todos', JSON.stringify(newValue))}}},methods: {addTodo(todoObj) {this.todos.unshift(todoObj)},checkTodo(todoObj) {this.todos.forEach((todo) => {if (todo.id == todoObj.id) {todo.done = !todo.done}})},updateTodo(todoObj, title) {this.todos.forEach((todo) => {if (todo.id == todoObj.id) {todo.title = title}})},deleteTodo(messageName, todoObj) {this.todos = this.todos.filter((todo) => {return todo.id !== todoObj.id})},checkAllTodo(value) {this.todos.forEach((todo) => {todo.done = value})},deleteAllTodo() {//用错了 把filter用成了forEach,而forEach只是个操作,不返回任何值也就是undefined//所以最终会将一个undefined赋值给todosthis.todos=this.todos.filter((todo) => {return !todo.done})}},mounted() {this.$bus.$on('checkTodo', this.checkTodo)this.$bus.$on('updateTodo', this.updateTodo)this.pubId=pubsub.subscribe('deleteTodo', this.deleteTodo)},beforeDestroy() {this.$bus.$off('checkTodo')this.$bus.$off('updateTodo')pubsub.unsubscribe(this.pubId)}
}
</script><style></style>

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

App托管服务分发平台 index-uplog.php 文件上传致RCE漏洞复现

0x01 产品简介 App托管服务分发平台是一个为开发者提供全面、高效、安全的应用程序托管、分发和推广服务的平台。开发者可以将自己开发的应用程序上传到平台上,平台会对上传的应用程序进行审核,确保应用的质量和安全性。平台会根据开发者的要求,将应用分发到不同的应用市场…

5G RAN

两个entity&#xff1a;NodeB、UE entity之间传输数据的东东 entity内部的流水线岗位&#xff1a;L3/L2/L1 岗位之间是消息交互/信令交互

利用labelme制作自己的coco数据集(labelme转coco数据集)

最近刚接触学习mmdetection&#xff0c;需要用到coco格式的数据集。 1.安装labelme 建议在conda(base)环境下安装&#xff08;前提是需要下载anaconda&#xff09;,下面是我已经装过的情况。 2.进入labelme环境下 中间可能会提示安装其它库&#xff0c;自行装上就行。 这里的…

智能社区服务小程序的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;用户管理&#xff0c;房屋信息管理&#xff0c;住户信息管理&#xff0c;家政服务管理&#xff0c;家政预约管理&#xff0c;报修信息管理 微信端账号功能包括&#xff1a;系统首页&#xff0c;房屋信…

Flood Fill——AcWing 1097. 池塘计数

Flood Fill 定义 Flood Fill算法&#xff0c;又称为洪水填充或种子填充算法&#xff0c;是一种在图或网格数据结构中探索连通区域的搜索算法。它从一个初始节点&#xff08;种子点&#xff09;开始&#xff0c;将具有相同属性&#xff08;如颜色、值等&#xff09;的相邻节点…

P4. 微服务: 匹配系统(下)

P4. 微服务: 匹配系统 下 0 概述1 游戏同步系统1.1 游戏同步的设计1.2 游戏同步的实现 2 匹配系统微服务的实现2.1 微服务概述2.2 匹配系统接口url的实现2.3 微服务之间的通信2.4 匹配逻辑的实现2.5 匹配系统的权限控制 3 bug的解决3.1 自己匹配自己3.2 断开连接问题 0 概述 本…

大数据之Linux部署常用命令脚本封装

文章目录 编写集群命令执行脚本xcall集群命令执行1. 脚本需求2. 需求分析3. 脚本实现3.1 创建脚本存放目录3.2 编写xcall脚本3.3 修改脚本执行权限3.4 测试脚本 编写集群分发脚本xsync集群分发脚本1. 脚本需求2. 需求分析3. 脚本实现3.1 创建脚本存放目录3.2 编写xsync脚本3.3 …

计算机毕业设计PyFlink+Spark+Hive民宿推荐系统 酒店推荐系统 民宿酒店数据分析可视化大屏 民宿爬虫 民宿大数据 知识图谱 机器学习

本科毕业设计(论文) 开题报告 学院 &#xff1a; 计算机学院 课题名称 &#xff1a; 民宿数据可视化分析系统的设计与实现 姓名 &#xff1a; 庄贵远 学号 &#xff1a; 2020135232 专业 &#xff1a; 数据科学与大数据技术 班级 &#xff1a; 20大数据本科2…

重温react-06(初识函数组件和快速生成格式的插件使用方式)

开始 函数组件必然成为未来发展的趋势(个人见解),总之努力的去学习,才能赚更多的钱.加油呀! 函数组件的格式 import React from reactexport default function LearnFunction01() {return (<div>LearnFunction01</div>) }以上是函数式组件的组基本的方式 快捷生…

基于DSMM数据安全能力建设方案的落地性评估指标

写在前面&#xff1a; 随着信息技术的迅猛发展&#xff0c;数据已成为企业最宝贵的资产之一。然而&#xff0c;数据安全问题也随之而来&#xff0c;如何确保数据的安全性、完整性和可用性&#xff0c;已成为企业面临的重要挑战。DSMM&#xff08;数据安全能力成熟度模型&#x…

混合专家模型(MoE)的前世今生

在文章《聊聊最近很火的混合专家模型&#xff08;MoE&#xff09;》中&#xff0c;我们简单介绍了MoE模型的定义和设计&#xff0c;并且比较了MoE和Dense模型的区别&#xff0c;今天我们继续来回顾一下MoE模型发展的历史和最新的发展现状。 从去年GPT-4发布至今&#xff0c;MoE…

[C++][设计模式][中介者模式]详细讲解

目录 1.动机2.模式定义3.要点总结 1.动机 在软件构建过程中&#xff0c;经常会出现多个对象相互关联的情况&#xff0c;对象之间常常会维持一种复杂的引用关系&#xff0c;如果遇到一些需求的更改&#xff0c;这种直接的引用关系将面临不断的变化在这种情况下&#xff0c;可以…

SpringDataJPA系列(2)Commons核心Repository

SpringDataJPA系列(2)Commons核心Repository Spring Data Commons依赖关系 我们通过 Gradle 看一下项目依赖&#xff0c;了解一下 Spring Data Common 的依赖关系 通过上图的项目依赖&#xff0c;不难发现&#xff0c;数据库连接用的是 JDBC&#xff0c;连接池用的是 HikariC…

使用label-studio对OCR数据进行预标注

导读 label-studio作为一款数据标注工具相信大家都不陌生&#xff0c;对于需要进行web数据标注协同来说应该是必备工具了&#xff0c;标注的数据类型很全涉及AI的各个任务(图像、语音、NLP、视频等)&#xff0c;还支持自定义涉及模版。 然而&#xff0c;我们在标注数据的过程…

Veno File Manager(VFM)v4.2.7 中文包整理

Veno File Manager&#xff08;VFM&#xff09;是一个简单灵活的即插即用文件管理器&#xff0c;易于使用且具有许多选项。将文件发送给您的客户&#xff0c;使用专用文件夹创建新用户&#xff0c;或仅用作您的个人文件云。从任何设备访问&#xff0c;用户管理和从直观的管理面…

OpenCV 调用自定义训练的 YOLO-V8 Onnx 模型

一、YOLO-V8 转 Onnx 在本专栏的前面几篇文章中&#xff0c;我们使用 ultralytics 公司开源发布的 YOLO-V8 模型&#xff0c;分别 Fine-Tuning 实验了 目标检测、关键点检测、分类 任务&#xff0c;实验后发现效果都非常的不错&#xff0c;但是前面的演示都是基于 ultralytics…

C语言分支和循环(下)

C语言分支和循环&#xff08;下&#xff09; 1. 随机数生成1.1 rand1.2 srand1.3 time1.4 设置随机数的范围 2. 猜数字游戏实现 掌握了前面学习的这些知识&#xff0c;我们就可以写⼀些稍微有趣的代码了&#xff0c;比如&#xff1a; 写⼀个猜数字游戏 游戏要求&#xff1a; 电…

第6章 复制

文章目录 前言1.配置1.1建立复制1.2断开复制1.3 安全性1.4 只读1.5 传输延迟 2. 拓扑2.1.一主一从结构2.2.一主多从结构2.3.树状主从结构 3.原理3.1复制过程3.2数据同步3.3全量复制 前言 复制功能&#xff0c;实现了相同数据的多个Redis副本。复制功能是高可用Redis的基础&…

智能交通(2)——IntelliLight智能交通灯

论文分享&#xff1a;IntelliLight | Proceedings of the 24th ACM SIGKDD International Conference on Knowledge Discovery & Data Mininghttps://dl.acm.org/doi/10.1145/3219819.3220096摘要 智能交通灯控制对于高效的交通系统至关重要。目前现有的交通信号灯大多由手…

【Python系列】列表推导式:简洁而强大的数据操作工具

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…