Vue基础14之TodoList组件自定义事件、全局事件总线、TodoList全局事件总线

news/2024/4/20 11:22:01/文章来源:https://blog.csdn.net/qq_34306228/article/details/129088253

Vue基础14

  • TodoList-组件自定义事件
    • 先改Header和Footer子组件,List先不考虑
      • App.vue
      • MyHeader.vue
      • MyFooter.vue
  • 全局事件总线
    • 实现思路
    • 正规写法
      • main.js
      • App.vue
      • Student.vue
      • School.vue
    • 总结:全局事件总线(GlobalEventBus)
  • TodoList案例:全局事件总线
    • App.vue
    • MyItem.vue
    • MyList.vue

TodoList-组件自定义事件

先改Header和Footer子组件,List先不考虑

App.vue

<MyHeader  @addTodo="addTodo"/>
<MyFooter :todos="todos" @clearAllTodo="clearAllTodo" @checkAllTodo="checkAllTodo"/>

Header.vue

add(){if(!this.title.trim()) return alert('输入的值不能为空!');const todoObj={id:nanoid(),title:this.title,done:false};this.$emit("addTodo",todoObj)this.title=''}

Footer.vue

props:['todos'],
isAll:{get(){return this.haveDone===this.total&&this.total>0},set(value){// this.todos.forEach(todo=>todo.done=value)// this.checkAllTodo(value)this.$emit("checkAllTodo",value)}}
methods:{checkAll(e){// this.checkAllTodo(e.target.checked)this.$emit("checkAllTodo",e.target.checked)},clearAll(){if(confirm('确定删除已完成任务吗?')){// this.clearAllTodo()this.$emit("clearAllTodo")}}}

App.vue

<template><div class="bg"><div class="todoList"><h2 class="title">待办事项</h2><MyHeader  @addTodo="addTodo"/><div class="listItem" v-show="todos.length"><MyList :todos="todos" :deleteTodo="deleteTodo" :checkTodo="checkTodo"/><MyFooter :todos="todos" @clearAllTodo="clearAllTodo" @checkAllTodo="checkAllTodo"/></div></div></div>
</template><script>
import MyHeader from "@/components/MyHeader";
import MyList from '@/components/MyList';
import MyFooter from '@/components/MyFooter'
export default {name: "App",components:{MyHeader, MyList, MyFooter},data(){return{todos:JSON.parse(localStorage.getItem('todos'))||[]}},methods:{//添加一个todoaddTodo(todoObj){this.todos.unshift(todoObj)},//删除一个tododeleteTodo(id){this.todos=this.todos.filter(todo=>todo.id!==id)},//勾选or取消勾选一个todocheckTodo(id){this.todos.forEach((todo)=>{if(todo.id===id){todo.done=!todo.done}})},//清除已完成任务clearAllTodo() {this.todos=this.todos.filter(todo=>!todo.done)},//全选or取消全选checkAllTodo(done){this.todos.forEach(todo=>todo.done=done)}},watch:{todos:{//开启深度监视deep:true,handler(value){localStorage.setItem('todos',JSON.stringify(value))}}}
}
</script><style lang="less">
*{padding: 0;margin: 0;
}
.bg{background-color: #333;height: 937px;padding-top: 100px;box-sizing: border-box;.todoList{background-color: #fff;width: 50%;height: 90%;margin: 0 auto;//box-shadow: 5px 5px 10px 3px rgba(147, 221, 255, 0.5),-5px -5px 10px 3px rgba(147, 221, 255, 0.5);  蓝色阴影box-shadow: 5px 5px 10px 3px rgba(0, 0, 0, 0.5),-5px -5px 10px 3px rgba(0, 0, 0, 0.5);padding-top: 20px;box-sizing: border-box;.title{text-align: center;font-size: 30px;font-weight: 300;color: #00a4ff;}.listItem{width: 90%;//height: 200px;margin: auto;/*background-color: pink;*/list-style: none;border-radius: 0 0 5px 5px;box-shadow: 1px 1px 5px 1px rgba(0,0,0,0.1),-1px -1px 5px 1px rgba(0,0,0,0.1);padding: 20px 0;box-sizing: border-box;}}
}
</style>

MyHeader.vue

<template><div><input type="text" class="content" @keyup.enter="add" placeholder="请输入你的任务名称,按回车键确认" v-model="title"></div>
</template><script>
import {nanoid} from 'nanoid';
export default {name: "MyHeader",data(){return{title:''}},methods:{add(){if(!this.title.trim()) return alert('输入的值不能为空!');const todoObj={id:nanoid(),title:this.title,done:false};this.$emit("addTodo",todoObj)this.title=''}}
}
</script><style scoped lang="less">
div{width: 90%;height: 8%;background-color: #ffffff;box-shadow: 1px 1px 5px 1px rgba(0,0,0,0.1),-1px -1px 5px 1px rgba(0,0,0,0.1);margin: 10px auto 2px auto;display: flex;.content{width: 95%;height: 80%;font-size: 25px;outline: none;display: block;margin: auto;justify-content: center;align-self: center;border: none;}
}
</style>

MyFooter.vue

<template><div>
<!--    <input type="checkbox" name="matter" id="" :checked="isAll" @change="checkAll">--><input type="checkbox" name="matter" id="" v-model="isAll">&nbsp;已完成 <span>{{haveDone}}</span> / 全部 <span>{{total}}</span><button @click="clearAll">清除已完成任务</button></div>
</template><script>
export default {name: "MyFooter",props:['todos'],computed:{total(){return this.todos.length},haveDone(){return this.todos.reduce((pre,current)=>{return pre+(current.done?1:0)},0)},// isAll(){//   return this.haveDone===this.total&&this.total>0// },isAll:{get(){return this.haveDone===this.total&&this.total>0},set(value){// this.todos.forEach(todo=>todo.done=value)// this.checkAllTodo(value)this.$emit("checkAllTodo",value)}}},methods:{checkAll(e){// this.checkAllTodo(e.target.checked)this.$emit("checkAllTodo",e.target.checked)},clearAll(){if(confirm('确定删除已完成任务吗?')){// this.clearAllTodo()this.$emit("clearAllTodo")}}}}
</script><style scoped lang="less">
div{width: 95%;margin: auto;margin-top: 10px;//border: 1px solid rgba(87, 87, 87, 0.3);button{background-color: #d9534f;float: right;padding: 3px 10px;color: white;border: 1px solid #d43f3a;border-radius: 5px;cursor: pointer;&:hover{background-color: #c9302c;border: 1px solid #ac2925;}}
}
</style>

Chrome浏览器安装Vue legacy插件才能显示自定义事件

请添加图片描述

全局事件总线

使用一个中间者x组件作为桥梁,实现任意组件之间能够通信
在这里插入图片描述

实现思路

  1. 第一步:所有人都能有回调函数
    知识点回顾:
    参考:Vue基础8的非单文件组件的一个重要的内置关系:VueComponent的原型对象是继承Vue的原型对象的
    在这里插入图片描述
    应用在项目中:
    在main.js里:
//1.生成一个VueComponent构造函数
const Demo=Vue.extend({})
//2.new一个VC对象
const d=new Demo()
//3.在原型中放置这个x为刚创建的VC
Vue.prototype.x=d

main.js

import Vue from 'vue';import App from './App'Vue.config.productionTip=false//1.生成一个VueComponent构造函数
const Demo=Vue.extend({})
//2.new一个VC对象
const d=new Demo()
//3.在原型中放置这个x为刚创建的VC
Vue.prototype.x=dnew Vue({el:"#app",render:h=>h(App),
})
  1. 实现Student.vue与School.vue组件之间通信
    School.vue
<template><div class="school"><h1>学校名称:{{name}}</h1><h1>学校地址:{{address}}</h1><h2 v-if="studentName">学生的姓名是:{{studentName}}</h2></div>
</template><script>
export default {name: "School",data(){return{name:"幸福中学",address:"重庆市渝北区",studentName:""}},mounted(){this.x.$on("hello",(value)=>{this.studentName=value})}
}
</script><style scoped>
.school{background-color: skyblue;
}
</style>

Student.vue

<template><div class="student"><h1>学生姓名:{{name}}</h1><h1>学生性别:{{sex}}</h1><button @click="showMsg">点我输出学生姓名</button></div>
</template><script>export default {name: "Student",data(){return{name:'李四',sex:'女'}},methods:{showMsg(){this.x.$emit("hello",this.name)}}}
</script><style scoped>
.student{background-color: pink;
}
</style>

请添加图片描述

正规写法

Vue原型身上的$on,$off,$emit不仅VC能调用到,Vm也可以
但是以下写法会报错:

//创建vm
const vm=new Vue({el:"#app",render:h=>h(App)
})Vue.prototype.x=vm

因为new Vue代码执行完毕后,意味着整个App组件(包括子组件School)都放到页面上去了,这时候再给原型x放vm已经晚了,这时可以借助生命周期函数使这一步有效。

正规写法如下:

main.js

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

App.vue

<template><div class="main"><h1>{{msg}}</h1><School /><Student /></div>
</template><script>
import School from "@/components/School";
import Student from "@/components/Student";
export default {name: "App",data() {return {msg: "你好啊!",}},components:{School,Student},
}
</script><style scoped>
.main{background-color: grey;padding: 5px;
}
</style>

Student.vue

<template><div class="student"><h1>学生姓名:{{name}}</h1><h1>学生性别:{{sex}}</h1><button @click="showMsg">点我输出学生姓名</button></div>
</template><script>export default {name: "Student",data(){return{name:'李四',sex:'女'}},methods:{showMsg(){// this.x.$emit("hello",this.name)this.$bus.$emit("hello",this.name)}}}
</script><style scoped>
.student{background-color: pink;
}
</style>

School.vue

<template><div class="school"><h1>学校名称:{{name}}</h1><h1>学校地址:{{address}}</h1><h2 v-if="studentName">学生的姓名是:{{studentName}}</h2></div>
</template><script>
export default {name: "School",data(){return{name:"幸福中学",address:"重庆市渝北区",studentName:""}},mounted(){// this.x.$on("hello",(value)=>{//   this.studentName=value// })this.$bus.$on("hello",(data)=>{this.studentName=data})},beforeDestroy(){this.$bus.off("hello")}
}
</script><style scoped>
.school{background-color: skyblue;
}
</style>

请添加图片描述

总结:全局事件总线(GlobalEventBus)

  1. 一种组件间通信的方式,适用于任意组件间通信
  2. 安装全局事件总线:

new Vue({

beforeCreate(){
Vue.prototype.$bus=this //安装全局事件总线,$bus就是当前应用的vm
},

})

  1. 使用事件总线:
    (1)接收数据:A组件想要接收数据,则在A组件中给$bus绑定自定义事件,事件的回调留在A组件自身

    methods(){
    demo(data){…}
    }

    mounted(){
    this.$bus.$on(‘xxx’,this.demo)
    }

(2)提供数据:

this.$bus.$emit(‘xxx’,数据)

  1. 最好在beforeDestroy钩子中,用$off去解绑当前组件所用到的事件

TodoList案例:全局事件总线

对于Item到App之间的传值,建议使用全局事件总线来传递,这样就不用List作为桥梁传递了

App.vue:

mounted(){//使用公共组件实现父组件和孙子组件传值this.$bus.$on("deleteTodo",this.deleteTodo)this.$bus.$on("checkTodo",this.checkTodo)},beforeDestroy() {//销毁公共组件的不再使用的组件this.$bus.$off("deleteTodo")this.$bus.$off("checkTodo")}

MyItem.vue:

export default {name: "MyItem",props:['todo'],methods:{deleteItem(id){//触发公共组件的某个事件if(confirm('确认删除嘛?'))  this.$bus.$emit("deleteTodo",id)},checkDone(id){//触发公共组件的某个事件this.$bus.$emit("checkTodo",id)}}
}

完整代码:

App.vue

<template><div class="bg"><div class="todoList"><h2 class="title">待办事项</h2><MyHeader  @addTodo="addTodo"/><div class="listItem" v-show="todos.length"><MyList :todos="todos"/><MyFooter :todos="todos" @clearAllTodo="clearAllTodo" @checkAllTodo="checkAllTodo"/></div></div></div>
</template><script>
import MyHeader from "@/components/MyHeader";
import MyList from '@/components/MyList';
import MyFooter from '@/components/MyFooter'
export default {name: "App",components:{MyHeader, MyList, MyFooter},data(){return{todos:JSON.parse(localStorage.getItem('todos'))||[]}},methods:{//添加一个todoaddTodo(todoObj){this.todos.unshift(todoObj)},//删除一个tododeleteTodo(id){this.todos=this.todos.filter(todo=>todo.id!==id)},//勾选or取消勾选一个todocheckTodo(id){this.todos.forEach((todo)=>{if(todo.id===id){todo.done=!todo.done}})},//清除已完成任务clearAllTodo() {this.todos=this.todos.filter(todo=>!todo.done)},//全选or取消全选checkAllTodo(done){this.todos.forEach(todo=>todo.done=done)}},watch:{todos:{//开启深度监视deep:true,handler(value){localStorage.setItem('todos',JSON.stringify(value))}}},mounted(){//使用公共组件实现父组件和孙子组件传值this.$bus.$on("deleteTodo",this.deleteTodo)this.$bus.$on("checkTodo",this.checkTodo)},beforeDestroy() {//销毁公共组件的不再使用的组件this.$bus.$off("deleteTodo")this.$bus.$off("checkTodo")}
}
</script><style lang="less">
*{padding: 0;margin: 0;
}
.bg{background-color: #333;height: 937px;padding-top: 100px;box-sizing: border-box;.todoList{background-color: #fff;width: 50%;height: 90%;margin: 0 auto;//box-shadow: 5px 5px 10px 3px rgba(147, 221, 255, 0.5),-5px -5px 10px 3px rgba(147, 221, 255, 0.5);  蓝色阴影box-shadow: 5px 5px 10px 3px rgba(0, 0, 0, 0.5),-5px -5px 10px 3px rgba(0, 0, 0, 0.5);padding-top: 20px;box-sizing: border-box;.title{text-align: center;font-size: 30px;font-weight: 300;color: #00a4ff;}.listItem{width: 90%;//height: 200px;margin: auto;/*background-color: pink;*/list-style: none;border-radius: 0 0 5px 5px;box-shadow: 1px 1px 5px 1px rgba(0,0,0,0.1),-1px -1px 5px 1px rgba(0,0,0,0.1);padding: 20px 0;box-sizing: border-box;}}
}
</style>

MyItem.vue

<template><div><li><!--      <input type="checkbox" name="matter" id="" v-model="todo.done">--><input type="checkbox" name="matter" id="" @change="checkDone(todo.id)" :checked="todo.done">&nbsp;{{todo.title}}<button class="delete" @click="deleteItem(todo.id)">删除</button></li></div>
</template><script>
export default {name: "MyItem",props:['todo'],methods:{deleteItem(id){//触发公共组件的某个事件if(confirm('确认删除嘛?'))  this.$bus.$emit("deleteTodo",id)},checkDone(id){//触发公共组件的某个事件this.$bus.$emit("checkTodo",id)}}
}
</script><style scoped lang="less">
li{//height: 35%;//width: 96%;display: block;//background-color: pink;margin: auto;padding: 12px;border-top: 1px solid rgba(87, 87, 87, 0.3);//border-left: 1px solid rgba(87, 87, 87, 0.3);//border-right: 1px solid rgba(87, 87, 87, 0.3);//box-sizing: border-box;border-collapse: collapse;button{background-color: #d9534f;float: right;padding: 3px 10px;color: white;border: 1px solid #d43f3a;border-radius: 5px;cursor: pointer;&:hover{background-color: #c9302c;border: 1px solid #ac2925;}}&:hover{background-color: rgba(0,0,0,0.1);}
}
</style>

MyList.vue

<template><div><ul><div class="con"><MyItem v-for="todo in todos" :todo="todo" :key="todo.id"/></div></ul></div>
</template><script>
import MyItem from "@/components/MyItem";
export default {name:'MyList',components:{MyItem},props:['todos']
}
</script><style scoped lang="less">
ul{.con{//width: 95%;//margin: auto;border-bottom: 1px solid rgba(87, 87, 87, 0.3);border-left: 1px solid rgba(87, 87, 87, 0.3);border-right: 1px solid rgba(87, 87, 87, 0.3);margin: 0px 8px;//background-color: pink;}
}
</style>

请添加图片描述

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

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

相关文章

修复 K8s SSL/TLS 漏洞(CVE-2016-2183)指南

作者&#xff1a;老 Z&#xff0c;中电信数智科技有限公司山东分公司运维架构师&#xff0c;云原生爱好者&#xff0c;目前专注于云原生运维&#xff0c;云原生领域技术栈涉及 Kubernetes、KubeSphere、DevOps、OpenStack、Ansible 等。 前言 测试服务器配置 主机名IPCPU内存系…

5.10 BGP属性-MED

5.4.4配置BGP MED属性控制选路 1. 实验目的 熟悉BGP MED属性控制选路的应用场景掌握BGP MED属性控制选路的配置方法2. 实验拓扑 实验拓扑如图5-10所示: 图5-10:配置BGP MED属性控制选路 3. 实验步骤 (1) 网络连通性 R1…

QMap 判断是否value是否已经存在,结合Sleep函数测试

网上查了资料&#xff0c;基本说的都是通过.value判断是否已经之前的key值&#xff0c;但是尝试.了一下发现有.key的函数&#xff0c;对比着来就感觉这个函数是用来判断是否已经存在value值&#xff0c;于是开始百度也几乎没有找到相关资料&#xff0c;只好自己看官方文档&…

【高速电路01】高速电路入门知识

1.什么是高速电路&#xff1f; 一般情况下&#xff0c;我们在讨论电路的特性时&#xff0c;一个基本的常识&#xff0c;是认为一条导线上各处的电压&#xff08;或者说信号&#xff09;在同一时刻是相等的。 以上结论在低速电路时是没问题的&#xff0c;但是&#xff0c;实际…

R语言、MaxEnt模型融合技术的物种分布模拟、参数优化方法、结果分析制图与论文写作

基于R语言、MaxEnt模型融合技术的物种分布模拟、参数优化方法、结果分析制图与论文写作技术应用第一章、理论篇以问题导入的方式&#xff0c;深入掌握原理基础什么是MaxEnt模型&#xff1f;MaxEnt模型的原理是什么&#xff1f;有哪些用途&#xff1f;MaxEnt运行需要哪些输入文件…

【异常】记一次因注解@RestController没加(@RestController不会用),导致无法调用Controller层的方法

一、背景 我想要调用一个Controller&#xff0c;定义的内容如下 RequestMapping("/demo") public class demoController {GetMapping("/doSomething")public JSONObject doSomething() {JSONObject json new JSONObject();json.set("title", …

界面控件DevExpress WPF Pivot Grid——拥有强大多维数据分析能力!

界面控件DevExpress WPF的Pivot Grid组件是一个类似excel的数据透视表&#xff0c;用于多维数据分析和跨选项卡报表生成。它拥有众多的布局自定义选项&#xff0c;允许开发者完全控制其UI且以用户为中心的功能使其易于部署。PS&#xff1a;DevExpress WPF拥有120个控件和库&…

双因素方差分析全流程

上篇文章讲述了“单因素方差分析全流程总结”&#xff0c;单因素方差分析只是考虑了一个自变量&#xff08;定类&#xff09;与一个因变量&#xff08;定量&#xff09;之间的关系&#xff0c;但是在实际问题研究中可能研究两个或者几个因素与因变量之间的关系&#xff0c;例如…

核心技术: springboot 启动类加载时方法执行的几种实现方式, bean声明周期, 启动执行顺序

目录 1. 业务场景 -> 1.1 初始化操作 -> 1.2 业务操作 -> 1.3优势 2. 实现方式(多种方式,不同思想) -> 2.1 定时调度任务(常用四种方式 task ) --> 2.1.1 Timer(单线程) --> 2.1.2 scheduledExecutorService(多线程并发执行,线程池) --> 2.1…

linux部署zookeeper

linux部署zookeeper 1、单机部署zk ZooKeeper服务器是用Java创建的&#xff0c;它需要在JVM上运行&#xff0c;所以需要使用JDK1.6及以上版本&#xff0c;一般都是jdk1.8。 选择自己安装本地的jdk&#xff0c;而不是centos自带的openjdk。 查看本地安装的jdk&#xff1a; j…

【C++的OpenCV】第二课-CMake创建OpenCV项目

文章目录一、CMake是什么&#xff1f;1.1 基本概念1.2 CMake的优势二、使用Cmake构建一个OpenCV程序2.1 步骤&#xff08;a&#xff09;编写一个简单的OpenCV示例代码&#xff08;b&#xff09;创建一个Cmake文件&#xff08;c&#xff09;生成可执行文件&#xff08;d&#xf…

DAX 微信 markdown 编辑器

DAX 微信 markdown 编辑器 一、致谢 感谢开源项目&#xff1a; md wechat-format 感谢 WordPress 插件 Mine云点播 作者 mine27 的指导。 二、如何使用 打开如下地址&#xff0c;直接编辑&#xff0c;可以实时看到符合微信公众号排版的效果。 推荐访问&#xff1a;https://j…

线上问题诊断指南

内容概要 诊断工具介绍工具可用情况偶现或已现问题诊断思路 硬件资源观测 top top可以看整个系统cpu、内存的使用情况&#xff0c;以及在各个进程上的情况&#xff0c;如下&#xff1a; $ top top - 13:14:07 up 2 days, 6:38, 0 users, load average: 1.65, 0.59, 0.27…

只因小黑子:SVG

小黑子的SVG复习SFV画布1. 初始SVG2. SVG绘制矩形、圆形和椭圆形2.1 rect 矩形2.2 circle 圆形2.3 ellipse 椭圆4. SVG绘制线条、多边形和多线条4.1 line 线条4.2 polygon 多边形4.3 polyline 多线条5. SVG绘制文本 text6. SVG绘制路径 path7. SVG描边属性8. SVG 模糊和阴影效果…

vue3.2中使用swiper缩略图轮播教程

介绍 在vue3 中使用 swiper 实现缩略图的轮播图效果,具体如下图所示: 使用 切换到项目终端 ,输入命令 npm install swiper --save , 进行安装在 main.js里,引入 swiper.css并使用,具体代码如下;import {createApp } from vue import App from ./App.vue import router…

查询服务器tns文件路径,oracle数据库tns配置方法详解

查询服务器tns文件路径,oracle数据库tns配置方法详解 TNS简要介绍与应用 Oracle中TNS的完整定义&#xff1a;transparence Network Substrate透明网络底层&#xff0c; 监听服务是它重要的一部分&#xff0c;不是全部&#xff0c;不要把TNS当作只是监听器。 TNS是Oracle Net…

Centos7搭建hadoop3.3.4分布式集群

文章目录1、背景2、集群规划2.1 hdfs集群规划2.2 yarn集群规划3、集群搭建步骤3.1 安装JDK3.2 修改主机名和host映射3.3 配置时间同步3.4 关闭防火墙3.5 配置ssh免密登录3.5.1 新建hadoop部署用户3.5.2 配置hadoopdeploy用户到任意一台机器都免密登录3.7 配置hadoop3.7.1 创建目…

linux shell脚本详解

一、!/bin/bash --- 指定脚本解释器 二、注释 1、单行注释 以 # 开头的行就是注释 2、多行注释 一般使用第一种&#xff01;来注释 三、变量 只读变量 使用 readonly 命令可以将变量定义为只读变量&#xff0c;只读变量的值不能被改变。 删除变量 unset variable_name…

社招中级前端笔试面试题总结

HTTP世界全览 互联网上绝大部分资源都使用 HTTP 协议传输&#xff1b;浏览器是 HTTP 协议里的请求方&#xff0c;即 User Agent&#xff1b;服务器是 HTTP 协议里的应答方&#xff0c;常用的有 Apache 和 Nginx&#xff1b;CDN 位于浏览器和服务器之间&#xff0c;主要起到缓存…

前端页面jquery规范写法

使用最新版本的 jQuery 最新版本的 jQuery 会改进性能和增加新功能,若不是为了兼容旧浏览器,建议使用最新版本的 jQuery。以下是三条常见的 jQuery 语句,版本越新,性能越好: $(.elem) $(.elem, context) context.find(.elem) 结果 1.6.2 版执行次数远超两个老版本。 jQ…