Vue2-全局事件总线、消息的订阅与发布、TodoList的编辑功能、$nextTick、动画与过渡

🥔:高度自律即自由

更多Vue知识请点击——Vue.js

VUE2-Day9

    • 全局事件总线
      • 1、安装全局事件总线
      • 2、使用事件总线
        • (1)接收数据
        • (2)提供数据
        • (3)组件销毁前最好解绑
      • 3、TodoList中的孙传父
        • (1)首先在main.js中安装全局事件总线
        • (2)在App.vue中绑定全局自定义事件,并使用之前写好的回调
        • (3)Item中触发事件,并把数据id传过去
    • 消息的订阅与发布
      • (1)使用消息的订阅与发布
      • (2)TodoList案例使用消息的订阅与发布
    • TodoList的编辑功能
      • 1、整体思路
      • 2、给标签添加事件
      • 3、点击编辑按钮切换span为input
      • 4、失去焦点传数据
      • 5、App收数据
    • $nextTick
    • 动画与过渡
      • 进入离开动画三种写法

全局事件总线

一种组件间通信的方式,适用于任意组件间通信。通俗理解就是一个定义在所有组件之外的公共嘎达,这个嘎达可以有vm或vc上的同款$on、$off、$emit,也可以让所有组件都访问到。要想实现这个事情,只能在Vue.prototype上添加一个属性,值是vm或vc

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-q3OYNFD4-1692378989491)(D:\wxf\前端学习笔记\vue2+vue3\笔记图片\全局事件总线.png)]

vm.$emit( event, arg ) //触发当前实例上的事件,arg是传递给父组件的参数
vm.$on( event, fn )    //监听event事件后运行 fn
$off(type, fn)		   //注销消息方法 type:消息名称	fn:消息回调函数

1、安装全局事件总线

安装全局事件总线可以用vc也可以用vm,写在main.js里面

  • 用vc的话这么写:
const Demo = Vue.extend({});
const d = new Demo();
Vue.prototype.$bus = d;
  • 用vm的话这么写(我们通常用vm):
new Vue({el: '#app',render: (h) => h(App),//放这个函数里,是因为模板还未解析,这个函数在自定义事件定义之前,是不会报错滴beforeCreate() {Vue.prototype.$bus = this //安装全局事件总线},
})

在这里我们使用vm安装全局事件总线。

2、使用事件总线

(1)接收数据

接收数据:A组件想接收数据,则在A组件中给$bus绑定自定义事件,事件的回调留在A组件自身

methods(){demo(data){......}
}
......
mounted() {this.$bus.$on('xxxx',this.demo)
}

(2)提供数据

任意一个组件,都可以给上面说的A组件传数据

  methods:{sendStudentName(){this.$bus.$emit('xxxx',this.name)}
}

(3)组件销毁前最好解绑

最好在beforeDestroy钩子中,用`$of去解绑当前组件所用到的事件。
因为接收数据的组件A中定义的回调函数和自定义事件是绑定的,而这个用来接收数据的组件实例A都销毁了,回调函数也没了,那这个自定义事件也就没用了,你留着会污染全局环境。

beforeDestroy() {this.$bus.$off('hello')
}

3、TodoList中的孙传父

之前我们孙传父都是父亲传给儿子函数,儿子传给孙子函数,然后孙子再调用函数传值,很麻烦,但是现在我们可以用全局事件总线实现孙子给父亲传数据。此处只展示修改部分,记得把之前方法的相关代码删掉或注释掉。

(1)首先在main.js中安装全局事件总线

new Vue({el: '#app',render: h => h(App),beforeCreate() {Vue.prototype.$bus = this; //创建全局事件总线}
});

(2)在App.vue中绑定全局自定义事件,并使用之前写好的回调

mounted() {//挂载完成后给全局事件总线添加事件this.$bus.$on('changeTodo', this.changeTodo);this.$bus.$on('deleteTodo', this.deleteTodo);
},
beforeDestroy() {//最好在销毁前解绑this.$bus.$off(['changeTodo', 'deleteTodo']);
},

(3)Item中触发事件,并把数据id传过去

handleChange(id) {//触发全局事件总线中的事件this.$bus.$emit('changeTodo', id);
},
handleDelete(id) {if (confirm('确定要删除吗?'))  //点确定是true,取消是falsethis.$bus.$emit('deleteTodo', id);
}

消息的订阅与发布

(1)使用消息的订阅与发布

消息的订阅与发布用的不多,和全局事件总线写法差不多,但是全局事件总线更好,因为是在Vue身上操作,但是这个的话要引入第三方库,库有很多,比如pubsub-js

安装pubsub:npm i pubsub-js
引入:import pubsub from 'pubsub-js

接收数据:A组件想接收数据,则在A组件中订阅消息,订阅的回调留在A组件自身。
接收两个参数,第一个是消息名字,第二个是传过来的数据

methods(){demo(msgName,data){......}
}
......
mounted() {//订阅消息this.pubsubId = pubsub.subscribe('xxx',this.demo) 
},   
beforeDestroy() {//销毁时取消订阅pubsub.unsubscribe(this.pubsubId); 
},

提供数据:

methods: {sendStudentName() {// this.$bus.$emit('hello', this.name);//发布消息并传数据pubsub.publish('hello', this.name); }
},

可以对比一下前面的全局事件总线写法,个人认为写法差别不大。

可以尝试把TodoList案例里孙传父使用全局事件总线的写法改成使用消息订阅与发布试试。

(2)TodoList案例使用消息的订阅与发布

这里把**deleteTodo改成消息订阅与发布,changeTodo依旧使用全局事件总线**,大家可以仔细对比他们的区别。

  • App.vue(订阅消息/接收数据):
 mounted() {//挂载完成后给全局事件总线添加事件this.$bus.$on('changeTodo', this.changeTodo)// this.$bus.$on('deleteTodo', this.deleteTodo)//deleteTodo换一种方法 用订阅消息写this.pubsubIs = pubsub.subscribe('deleteTodo', this.deleteTodo)},beforeDestroy() {//最好在销毁前解绑// this.$bus.$off(['changeTodo', 'deleteTodo'])//使用全局事件总线解绑this.$bus.$off('changeTodo')//deleteTodo换一种方法 用订阅消息解绑pubsub.unsubscribe(this.pubsubId)},

这里别忘了这个subscribe里的回调,接收两个参数,第一个是消息名,后面才是数据,所以deleTodo方法得加个参数

//虽然msgName没用上,但是如果不加就会把id当第一个参数,id就变成msgName,所以这里必须要加,或者直接拿一个下划线_占位也行
deleteTodo(msgName, id) {this.todos = this.todos.filter(todo => todo.id !== id);},
  • Item.vue(发布消息/提供数据)
handleChange(id) {//使用全局事件总线//触发全局事件总线中的事件this.$bus.$emit('changeTodo', id);
},
handleDelete(id) {//confirm点确定是true,取消是falseif (confirm('确定要删除吗?')) //使用消息订阅与发布发布消息pubsub.publish('deleteTodo', id);  //发布消息
}

TodoList的编辑功能

1、整体思路

首先得有一个按钮,点击之后出现input框,框里是todo.title,而且原来的span要隐藏。然后修改完之后,失去焦点会自动更新数据,并且span出现,input框隐藏。
除此之外还有个细节,那就是点击编辑要自动获取焦点,要不然会有一个小问题(点击编辑,然后突然不想改了,还得手动点一下input,再点下别的地方,才会变回span)

想实现span和input的来回切换,就要给todo添加新的属性,用来标识这个变换,这里起名叫isEdit

所以大致思路:给标签添加事件 => 点击编辑按钮切换span为input => 失去焦点传数据 => App收数据 => 解决焦点bug

2、给标签添加事件

(1)isEdit一上来是没有的,所以todo.isEdit = false,再加上默认上来显示的是span,所以span加个v-show=“!todo.isEdit”,input加个v-show=“todo.isEdit” ,button加v-show="!todo.isEdit"是因为我们一般编辑时,这个按钮应该消失才对,所以和span一致

(2)由于props接过来的数据不能改,所以使用单向数据绑定:value=“todo.title”

(3)ref=“inputTitle” 是为了方便后面拿到input元素然后操作它写的(nextTick)

(4)@blur="handleBlur(todo, $event)"是失去焦点时触发的事件,用来给App传值

<span v-show="!todo.isEdit">{{ todo.title }}</span>
<input 
type="text" 
v-show="todo.isEdit" 
:value="todo.title" 
ref="inputTitle" 
@blur="handleBlur(todo, $event)"><button class="btn btn-edit" @click="handleEdit(todo)" v-show="!todo.isEdit">编辑</button>

给这个编辑按钮加个样式:

.btn-edit {color: #fff;background-color: rgb(13, 166, 13);border: 1px solid green;margin-right: 5px;
}.btn-edit:hover {color: #fff;background-color: green;
}

3、点击编辑按钮切换span为input

点击编辑给todo追加属性,用来切换span为input。这里考虑到给todo追加属性的问题,如果想要让Vue监测到这个属性,那么必须使用$set来添加isEdit,且默认值为true(因为编辑的时候显示的是input啊,想想v-show="todo.isEdit")。

但是这里边有点儿问题,如果已经添加过了isEdit,那每次点击编辑按钮,都会添加一次isEdit属性,这样是不太好的,所以要加个判断,添加过了就改成true,没添加过就添加个true

   handleEdit(todo) {if (todo.isEdit !== undefined) {console.log('todo里有isEdit属性了')todo.isEdit = true;} else {console.log('todo里没有isEdit属性')this.$set(todo, 'isEdit', true);}this.$nextTick(function () {this.$refs.inputTitle.focus();})},

4、失去焦点传数据

失去焦点首先input得变回span,然后使用全局事件总线传值,传值一定要传当前input框的value值,因为这才是你修改后的值,使用事件对象获取。(当然,别忘了id也要传)

handleBlur(todo, e) {todo.isEdit = false;if (!e.target.value.trim()) return alert('值不能为空!');  //trim去掉空格this.$bus.$emit('updateTodo', todo.id, e.target.value);
}

5、App收数据

把input框里你写的东西拿过来,给对应的todo.title

//6.实现编辑todo
methods: {......updateTodo(id, title) {this.todos.forEach((todo) => {if (todo.id === id) { todo.title = title }});}}
mounted() {......//实现编辑功能,接收数据this.$bus.$on('updateTodo', this.editTodo);
},
beforeDestroy() {//最好在销毁前解绑this.$bus.$off('updateTodo');
},

$nextTick

1、语法:this.$nextTick(回调函数)
2、作用:在下一次 DOM 更新结束,v-for循环结束后执行其指定的回调。
3、什么时候用:当改变数据后,要基于更新后的新DOM进行某些操作时(如input自动获取焦点),要在nextTick所指定的回调函数中执行。

4、比如刚才点击编辑后,input框没法自动获取焦点,那么我就得先点一下,再点别处儿才能切换回去,如果直接this.$refs.inputTitle.focus();不行,因为这个函数虽然动了isEdit的值,但是模板重新解析也得等这个函数走完啊,那input还没创建出来呢,就focus了,肯定是不行滴。
有个办法就是用异步,也可以解决,但是更好的办法是$nextTick

动画与过渡

1、作用:在插入、更新或移除 DOM元素时,在合适的时候给元素添加样式类名。

请添加图片描述

2、写法:

准备好样式:

元素进入的样式:
v-enter:进入的起点
v-enter-active:进入过程中
v-enter-to:进入的终点

元素离开的样式:
v-leave:离开的起点
v-leave-active:离开过程中
v-leave-to:离开的终点

使用<transition>包裹要过度的元素,并配置name属性:

<transition name="hello"><h1 v-show="isShow">你好啊!</h1>
</transition>

3、备注:若有多个元素需要过度,则需要使用:<transition-group>,且每个元素都要指定key值。

进入离开动画三种写法

  • 1、动画(Test.vue)
<template><div><button @click="isShow = !isShow">显示/隐藏</button><transition name="hello" appear><h1 v-show="isShow">你好呀!</h1></transition></div>
</template><script>
export default {name: 'Test',data() {return {isShow: true,}},
}
</script><style scoped>
h1 {background-color: pink;
}.hello-enter-active {animation: potato 1s;
}
.hello-leave-active {animation: potato 1s reverse;
}@keyframes potato {from {transform: translateX(-100%);}to {transform: translateX(0px);}
}
</style>
  • 2、过渡动画(Test2.vue)
<template><div><button @click="isShow = !isShow">显示/隐藏</button><transition-group name="hello" appear><h1 v-show="isShow" key="1">你好呀!</h1><h1 v-show="isShow" key="2">小土豆</h1></transition-group></div>
</template><script>
export default {name: 'Test2',data() {return {isShow: true,}},
}
</script><style scoped>
h1 {background-color: skyblue;
}/* 进入的起点,离开的终点 */
.hello-enter,
.hello-leave-to {transform: translateX(-100%);
}
/* 进入的终点,离开的起点 */
.hello-enter-to,
.hello-leave {transform: translateX(0);
}
.hello-enter-active,
.hello-leave-active {transition: 0.5s linear;
}
</style>
  • 3、集成第三方动画
<template><div><button @click="isShow = !isShow">显示/隐藏</button><transition-groupname="animate__animated animate__bounce"appearenter-active-class="animate__swing"leave-active-class="animate__backOutUp"><h1 v-show="isShow" key="1">你好呀!</h1><h1 v-show="isShow" key="2">小土豆</h1></transition-group></div>
</template><script>
import 'animate.css'
export default {name: 'Test3',data() {return {isShow: true,}},
}
</script><style scoped>
h1 {background-color: orange;
}
</style>
  • App.vue
<template><div id="App"><Test /><Test2 /><Test3 /></div>
</template><script>
import Test from './components/Test'
import Test2 from './components/Test2'
import Test3 from './components/Test3'
export default {name: 'App',components: { Test, Test2, Test3 },
}
</script>
  • 效果:(从上往下分别是Test、Test2、Test3效果)
    请添加图片描述

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

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

相关文章

LRU淘汰策略执行过程

1 介绍 Redis无论是惰性删除还是定期删除&#xff0c;都可能存在删除不尽的情况&#xff0c;无法删除完全&#xff0c;比如每次删除完过期的 key 还是超过 25%&#xff0c;且这些 key 再也不会被客户端访问。 这样的话&#xff0c;定期删除和堕性删除可能都彻底的清理掉。如果…

飞天使-k8s基础组件分析-pod

文章目录 pod介绍pod 生命周期init 容器容器handlerpod中容器共享进程空间sidecar 容器共享 参考链接 pod介绍 最小的容器单元 为啥需要pod? 答: 多个进程丢一个容器里&#xff0c;会因为容器里个别进程出问题而出现蝴蝶效应&#xff0c;pod 是更高级的处理方式pod 如何共享相…

机器学习深度学习——NLP实战(情感分析模型——RNN实现)

&#x1f468;‍&#x1f393;作者简介&#xff1a;一位即将上大四&#xff0c;正专攻机器学习的保研er &#x1f30c;上期文章&#xff1a;机器学习&&深度学习——NLP实战&#xff08;情感分析模型——数据集&#xff09; &#x1f4da;订阅专栏&#xff1a;机器学习&…

Hadoop学习:深入解析MapReduce的大数据魔力之数据压缩(四)

Hadoop学习&#xff1a;深入解析MapReduce的大数据魔力之数据压缩&#xff08;四&#xff09; 4.1 概述1&#xff09;压缩的好处和坏处2&#xff09;压缩原则 4.2 MR 支持的压缩编码4.3 压缩方式选择4.3.1 Gzip 压缩4.3.2 Bzip2 压缩4.3.3 Lzo 压缩4.3.4 Snappy 压缩4.3.5 压缩…

Nets3e v1.1.4(攻击者在受害者主机上偷拍并弹出受害者个人照片)

Github>https://github.com/MartinxMax/Nets3e/tree/Nets3e_V1.1.4 首页 历史更新: Nets3e v1.1.4 新增echo参数,-g -echo,生成payload后,受害者泄露的个人照片将会在受害者的主机上弹出展示 Nets3e v1.1.3 修复受害者无法获取公网IP,新增钉钉实时监控推送 Nets3e v1.1…

excel 动态表头与合并列

零、希望Springboot-java导出excel文件&#xff0c;包括动态表头与下边合并的列 使用 org.apache.poi 与自己封装工具类实现相关功能。代码如下 一、代码 1、依赖 implementation(group: org.apache.poi,name: poi-ooxml,version: 4.1.0)implementation(group: org.apache.po…

VR漫游:720度实景参观,打造魅力生态小区

随着城市的不断发展&#xff0c;小区的建设越发具有生态化、绿色化的特点&#xff0c;人们也会偏向选择更加适合居住的小区。为了让更多的用户体验小区的舒适性&#xff0c;不少地产开发商准备引入VR漫游技术。 VR漫游不仅能够真实地展示现场环境&#xff0c;还可以改变传统网络…

【数据结构】实现栈和队列

目录 一、栈1.栈的概念及结构&#xff08;1&#xff09;栈的概念&#xff08;2&#xff09;栈的结构 2.栈的实现&#xff08;1&#xff09;类型和函数的声明&#xff08;2&#xff09;初始化栈&#xff08;3&#xff09;销毁&#xff08;4&#xff09;入栈&#xff08;5&#x…

连接未来 驱动创新|腾讯云 CODING DevOps 主题沙龙诚邀您的参与

点击链接了解详情 随着企业数字化转型步入深水区&#xff0c;DevOps 作为数字化转型关键的内建阶段&#xff0c;其应用和实施已经成为企业提升研发效率&#xff0c;实现快速迭代和持续交付的重要手段。然而如何有效地实施 DevOps&#xff0c;如何利用 DevOps 推动业务发展和创新…

CSS加载失败的6个原因

有很多刚刚接触 CSS 的新手有时会遇到 CSS 加载失败这个问题&#xff0c;但测试时&#xff0c;网页上没有显示该样式的问题&#xff0c;这就说明 CSS 加载失败了。出现这种状况一般是因为的 CSS 路径书写错&#xff0c;或者是在浏览器中禁止掉了 CSS 的加载&#xff0c;可以重新…

vue3 路由缓存问题

目录 解决问题的思路&#xff1a; 解决问题的方案&#xff1a; 1、给roter-view添加key&#xff08;破坏复用机制&#xff0c;强制销毁重建&#xff09; 2、使用beforeRouteUpdate导航钩子 3、使用watch监听路由 vue3路由缓存&#xff1a;当用户从/users/johnny导航到/use…

[网络架构]Self-organized operational neural networks (SelfONN)

Self-organized operational neural networks (SelfONN 背景CNNONNSelfONNCNN, ONN&#xff0c; SelfONN对比SelfONN与CNN的关系总结References 背景 本节要分享的是SelfONN, SelfONN可以看作是ONN的优化/升级&#xff0c; 而ONN可以看作是更一般化的CNN&#xff0c; 克服了CN…

自己实现 SpringMVC 底层机制 系列之-实现任务阶段 6-完成控制器方法获取参数-@RequestParam

&#x1f600;前言 自己实现 SpringMVC 底层机制 系列之-实现任务阶段 6-完成控制器方法获取参数-RequestParam &#x1f3e0;个人主页&#xff1a;尘觉主页 &#x1f9d1;个人简介&#xff1a;大家好&#xff0c;我是尘觉&#xff0c;希望我的文章可以帮助到大家&#xff0c…

Feign:使用接口方式调用服务

创建一个新的消费者模块并导入依赖 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://ma…

Linux学习之firewallD

systemctl status firewalld.service查看一下firewalld服务的状态&#xff0c;发现状态是inactive (dead)。 systemctl start firewalld.service启动firewalld&#xff0c;systemctl status firewalld.service查看一下firewalld服务的状态&#xff0c;发现状态是active (runni…

无涯教程-PHP - preg_grep()函数

preg_grep() - 语法 array preg_grep ( string $pattern, array $input [, int $flags] ); 返回由与给定模式匹配的输入数组元素组成的数组。 如果将flag设置为PREG_GREP_INVERT&#xff0c;则此函数返回输入数组中与给定模式不匹配的元素。 preg_grep() - 返回值 返回使用…

pdf转word最简单方法~

pdf转word最简单方法&#xff01;pdf转word最简单方法我们都知道&#xff0c;PDF文件是一种只读文件格式&#xff0c;无法按照需求对PDF文件进行更改与编辑&#xff0c;从而影响到了PDF文件的使用。所以&#xff0c;我们需要将PDF文件转换为word文档&#xff0c;以此来保证文件…

LLM 生成式配置的推理参数温度 top k tokens等 Generative configuration inference parameters

在这个视频中&#xff0c;你将了解一些方法和相关的配置参数&#xff0c;这些参数可以用来影响模型在下一个词生成时的最终决策方式。如果你在Hugging Face网站或AWS的游乐场中使用过LLMs&#xff0c;你可能已经看到了这些控制选项&#xff0c;用来调整LLM的行为。每个模型都暴…

【数据库】表操作 习题总结

目录 关系建表 数据库sql的执行顺序 内外连接的写法 1.设计一张商品表 2.设计一张老师表 3.设计一张图书表 4.查询练习 5.查询练习 6.设计一个考勤系统 7.设计一个学校宿舍管理系统 8.设计一个车辆违章系统 9.设计一个学校食堂管理系统 10.有一张员工表emp&#xf…

AWS SDK 3.x for .NET Framework 4.0 可行性测试

前言 为了应对日益增长的网络安全挑战, 越来越多的互联网厂商已经陆续开始或者已经彻底停止了对 SSL 3 / TLS 1.0 / TLS1.1 等上古加密算法的支持. 而对于一些同样拥有悠久历史的和 AWS 服务相关联的应用程序, 是否可以通过仅更新 SDK 版本的方式来适应新的环境. 本文将以 Win…