Vue中 组件间的通信

news2024/11/24 15:03:08

目录

引入

父组件==>子组件

子组件==>父组件

全局事件总线

消息订阅与发布


引入

你知道Vue中组件之间应该如何进行通信吗?这里面就涉及到了多个关系了,父子之间互传、兄弟之间互传、子孙之间互传,甚至是任意的组件之间传递......

是不是感觉有点头皮发麻。没关系,本文将带领大家一起学习对应的解决方法!!!

父组件==>子组件

父组件若想传递信息给子组件,最常见的方式就是使用props配置项。该配置项的功能是让组件接受外部传过来的数据。

传递数据:<Demo name="xxx"/>

接收数据:

1.第一种方式(只接收):props:['name']

2.第二种方式(限制类型):props:{name:String}

3.第三种方式(限制类型、限制必要性、指定默认值):

props:{
    name:{
    type:String, //类型
    required:true, //必要性
    default:'老王' //默认值
    }
}

现在在脚手架中编写一个案例来实现父组件给子组件传递数据,并在页面上显示出来。默认的父组件为App, 子组件为Student。先从父组件传入三个数据给子组件,并且显示在页面上。接受方式分别采用以上的方式来实现,对应的代码如下:

App.vue

<template>
    <div>
        <!-- 为子组件传入数据 -->
        <Student name="N-A" sex="男" age="5"/>
    </div>
</template>
​
<script>
    //导入Student组件
    import Student from './components/Student'
    export default {
        name:'App',
    //注册Student组件
        components:{Student}
    }
</script>
​

Student.vue

<template>
    <div>
        <h1>{{msg}}</h1>
        <h2>博主姓名:{{name}}</h2>
        <h2>博主性别:{{sex}}</h2>
        <h2>博主年龄:{{age}}</h2>
    </div>
</template>
<script>
    export default {
        //组件名命名为Student
        name:'Student',
        data() {
            return {
                msg:'我是一名CSDN博主'
            }
        },
        //方式一:简单声明接收
        props:['name','sex',"age"]
​
        //方式二:接收的同时对数据进行类型限制
        props:{
            name:String,
            age:Number,
            sex:String
        } 
​
        //方式三:接收的同时对数据:进行类型限制+默认值的指定+必要性的限制
        props:{
            name:{
                type:String, //name的类型是字符串
                required:true, //name是必要的
            },
            age:{
                type:Number,
                default:99 //默认值
            },
            sex:{
                type:String,
                required:true
            }
        }
    }
</script>

分别运行以上代码提供的三种方式运行的效果图如上,三种方式都能够让数据在页面上进行显示。但是其中涉及到一些问题。图二为采用方式二来接收传入的数据时的控制台出现的错误,虽然能够在页面上看到数据,但是已经存在问题了,因为我们在接收数据时规定了age属性传入的数据的类型为number类型。

但是我们在传值时,编写了age="5", 因此传入的5则为字符串。那该如何解决呢?只需要在age前面加上冒号。对其进行绑定,绑定之后双引号之中的东西都会当成是JS的表达式去解析,因此,解析之后就是纯粹的数字5,因此就能够解决相应的问题。

现在我在增加一个要求,在页面上增加一个按钮通过点击之后来实现页面上的年龄加一的效果。对应代码如下:

<template>
    <div>
        <h1>{{msg}}</h1>
        <h2>博主姓名:{{name}}</h2>
        <h2>博主性别:{{sex}}</h2>
        <h2>博主年龄:{{MyAge}}</h2>
        <button @click="updateAge">年龄加一</button>
    </div>
</template>
​
<script>
    export default {
        name:'Student',
        data() {
            return {
                msg:'我是一名CSDN博主',
                MyAge:this.age
            }
        },
        methods: {
            updateAge(){
                this.MyAge++
            }
        },
        //简单声明接收
        props:['name','age','sex'] 
    }
</script>

效果能够正常显示。(在线请教各位小伙伴你们文章中的动图是怎样制作的。)看了以上的代码可能会有小伙伴会问,为啥子组件接收到的age数据不直接修改呢,直接修改也能够实现相应的效果。为啥还需要另一个设置MyAge来接收它,再修改MyAge的值呢?这时候就需要注意一下以下的注意事项了。

注意:props是只读的,Vue底层会监测你对props的修改,如果进行了修改,就会发出警告,若业务需求确实需要修改,那么请复制props的内容到data中一份,然后去修改data中的数据。

子组件==>父组件

实现方法一:通过父组件给子组件传递函数类型的props,从而实现子组件给父组件传递数据。在前面我们已经对props有了一定的了解了,那么现在我们就来通过代码实现吧!

案例:School组件有学校名以及学校地址两个信息,现在需要实现App父组件可以接收到School子组件传过来的学校名。

App.vue(父组件)

<template>
    <div class="app">
        <!-- 通过父组件给子组件传递函数类型的props实现:子给父传递数据 -->
        <School :getSchoolName="getSchoolName"/>
    </div>
</template>
​
<script>
    import School from './components/School'
    export default {
        name:'App',
        components:{School},
        methods: {
            getSchoolName(name){
                console.log('App收到了学校名:',name)
            }
        }
    }
</script>
​
<style scoped>
    .app{
        background-color: gray;
        padding: 5px;
    }
</style>

在App父组件中,定义了一个getSchoolName函数,并为子组件传递了该函数。

School.vue(子组件)

<template>
    <div class="school">
        <h2>学校名称:{{name}}</h2>
        <h2>学校地址:{{address}}</h2>
        <button @click="sendSchoolName">把学校名给App</button>
    </div>
</template>
​
<script>
    export default {
        name:'School',
        props:['getSchoolName'],
        data() {
            return {
                name:'史莱克学院',
                address:'天斗帝国',
            }
        },
        methods: {
            sendSchoolName(){
                this.getSchoolName(this.name)
            }
        },
    }
</script>
​
<style scoped>
    .school{
        background-color:rgb(212, 237, 210);
        padding: 5px;
    }
</style>

子组件使用props配置项接收了getSchoolName函数,在sendSchoolName函数中调用传过来的函数,并传入学校名。并为按钮绑定getSchoolName点击事件。通过点击之后来实现向父组件传递学校名的目的。对应的实现效果如下:



实现方法二:若子组件想要传数据给父组件,还可以使用组件的自定义事件。使用场景为:若A是父组件,B是子组件,B想给A传数据,那么就要在A中给B绑定自定义事件(事件的回调在A中)。

绑定自定义事件有如下的两种方式:

第一种方式,在父组件中:<Demo @自定义事件名="test"/><Demo v-on:自定义事件名="test"/>

案例还是上面的,通过修改第一种方式的自定义事件对应的代码如下:

App.vue(父组件)

<template>
    <div class="app">
        <!-- 通过父组件给子组件绑定一个自定义事件实现:子给父传递数据(第一种写法,使用@或v-on) -->
        <School @showName="getSchoolName"/>
    </div>
</template>
​
<script>
    import School from './components/School'
    export default {
        name:'App',
        components:{School},
        methods: {
            getSchoolName(name){
                console.log('App收到了学校名:',name)
            }
        },
    }
</script>
​
<style scoped>
    .app{
        background-color: gray;
        padding: 5px;
    }
</style>
​

School.vue(子组件)

<template>
    <div class="school">
        <h2>学校名称:{{name}}</h2>
        <h2>学校地址:{{address}}</h2>
        <button @click="sendSchoolName">把学校名给App</button>
    </div>
</template>
​
<script>
    export default {
        name:'School',
        data() {
            return {
                name:'史莱克学院',
                address:'天斗帝国',
            }
        },
        methods: {
            sendSchoolName(){
                //触发School组件实例身上的showName事件
                this.$emit('showName',this.name)
            }
        },
    }
</script>
​
<style scoped>
    .school{
        background-color:rgb(212, 237, 210);
        padding: 5px;
    }
</style>

实现效果如下:能够正常的显示出来!

第二种方式,只是在父组件中换一种绑定事件的方式,只需要修改父组件中代码:

<template>
	<div class="app">
		<!-- 通过父组件给子组件绑定一个自定义事件实现:子给父传递数据(第二种写法,使用ref) -->
		<School ref="school" />
	</div>
</template>

<script>
	import School from './components/School'
	export default {
		name:'App',
		components:{School},
		methods: {
			getSchoolName(name){
				console.log('App收到了学校名:',name)
			}
		},
		mounted() {
			this.$refs.school.$on('showName',this.getSchoolName) //绑定自定义事件
		},
	}
</script>

<style scoped>
	.app{
		background-color: gray;
		padding: 5px;
	}
</style>

实现效果与之上的相同。关于自定义事件的其他知识点,我就不在这里过多赘述,毕竟主要是分享它如何实现子组件向父组件传数据。

注意:通过this.$refs.xxx.$on('atguigu',回调)绑定自定义事件时,回调要么配置在methods中,要么用箭头函数,否则this指向会出问题!

全局事件总线

全局事件总线是一种组件间通信的方式,适用于任意组件间通信。

1.安装全局事件总线:

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

2.使用事件总线:

  • 接收数据:A组件想接收数据,则在A组件中给$bus绑定自定义事件,事件的回调留在A组件自身。
methods(){
  demo(data){......}
}
......
mounted() {
  this.$bus.$on('xxxx',this.demo)
}
  • 提供数据:this.$bus.$emit('xxxx',数据)

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

案例:现有两个兄弟组件,分别是Student组件以及School组件,要实现Student组件给School组件传送数据。对应的实现代码如下:

main.js入口文件,需要先安装全局事件总线。

//引入Vue
import Vue from 'vue'
//引入App
import App from './App.vue'
//关闭Vue的生产提示
Vue.config.productionTip = false
​
//创建vm
new Vue({
    el:'#app',
    render: h => h(App),
//安装全局事件总线
    beforeCreate() {
        Vue.prototype.$bus = this 
    }
})

提供数据方组件代码如下:

<template>
    <div class="student">
        <h2>学生姓名:{{name}}</h2>
        <h2>学生性别:{{sex}}</h2>
        <button @click="sendStudentName">把学生名给School组件</button>
    </div>
</template>
​
<script>
    export default {
        name:'Student',
        data() {
            return {
                name:'N-A',
                sex:'男',
            }
        },
        methods: {
            //提供数据
            sendStudentName(){
                this.$bus.$emit('hello',this.name)
            }
        },
    }
</script>
​
<style  scoped>
    .student{
        background-color:rgb(212, 237, 210);
        padding: 5px;
        margin-top: 30px;
    }
</style>

接收数据方组件代码如下:

<template>
    <div class="school">
        <h2>学校名称:{{name}}</h2>
        <h2>学校地址:{{address}}</h2>
    </div>
</template>
​
<script>
    export default {
        name:'School',
        data() {
            return {
                name:'史莱克学院',
                address:'天斗帝国',
            }
        },
        //绑定一个hello事件,用于接收数据
        mounted() {
            this.$bus.$on('hello',(data)=>{
                console.log('我是School组件,收到了数据',data)
            })
        },
        //用$off去解绑<span style="color:red">当前组件所用到的</span>事件。
        beforeDestroy() {
            this.$bus.$off('hello')
        },
    }
</script>
​
<style scoped>
    .school{
        background-color:rgb(212, 237, 210);
        padding: 5px;
    }
</style>

实现效果如下,兄弟组件之间实现了数据的传递。

消息订阅与发布

消息订阅与发布是一种组件间通信的方式,适用于任意组件间通信。使用方式如下:

1.安装pubsub:npm i pubsub-js

2.引入: import pubsub from 'pubsub-js'

3.接收数据:A组件想接收数据,则在A组件中订阅消息,订阅的回调留在A组件自身。

methods(){
  demo(data){......}
}
......
mounted() {
  this.pid = pubsub.subscribe('xxx',this.demo) //订阅消息
}

4.提供数据:pubsub.publish('xxx',数据)

5.最好在beforeDestroy钩子中,用PubSub.unsubscribe(pid)去取消订阅。

该方式与上述的全局事件总线比较相似,主要是不需要用到$bus,而是替换成了pubsub。

对以上的代码进行修改之后如下:

提供数据方组件代码如下:

<template>
    <div class="student">
        <h2>学生姓名:{{name}}</h2>
        <h2>学生性别:{{sex}}</h2>
        <button @click="sendStudentName">把学生名给School组件</button>
    </div>
</template>
​
<script>
    import pubsub from 'pubsub-js'
    export default {
        name:'Student',
        data() {
            return {
                name:'N-A',
                sex:'男',
            }
        },
        methods: {
            sendStudentName(){
                pubsub.publish('hello',this.name)
            }
        },
    }
</script>
​
<style  scoped>
    .student{
        background-color:rgb(212, 237, 210);
        padding: 5px;
        margin-top: 30px;
    }
</style>

接收数据方组件代码如下:

<template>
    <div class="school">
        <h2>学校名称:{{name}}</h2>
        <h2>学校地址:{{address}}</h2>
    </div>
</template>
​
<script>
    import pubsub from 'pubsub-js'
    export default {
        name:'School',
        data() {
            return {
                name:'史莱克学院',
                address:'天斗帝国',
            }
        },
        mounted() {
            this.pubId = pubsub.subscribe('hello',(msgName,data)=>{
                console.log(data)
            })
        },
        beforeDestroy() {
            pubsub.unsubscribe(this.pubId)
        },
    }
</script>
​
<style scoped>
    .school{
        background-color:rgb(212, 237, 210);
        padding: 5px;
    }
</style>

实现效果如下:

 好啦,本文就到这里结束了,你学到了吗?若有任何的疑问或者问题欢迎各位在评论区或者私信找我一起交流学习!

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

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

相关文章

Python基础教程: json序列化详细用法介绍

前言 嗨喽&#xff0c;大家好呀~这里是爱看美女的茜茜呐 Python内置的json模块提供了非常完善的对象到JSON格式的转换。 废话不多说&#xff0c;我们先看看如何把Python对象变成一个JSON&#xff1a; d dict(nameKaven, age17, sexMale) print(json.dumps(d)) # {"na…

C++:模拟实现list

文章目录 迭代器模拟实现 本篇模拟实现简单的list和一些其他注意的点 迭代器 如下所示是利用拷贝构造将一个链表中的数据挪动到另外一个链表中&#xff0c;构造两个相同的链表 list(const list<T>& lt) {emptyinit();for (auto e : lt){push_back(e);} }void test_…

【swagger2】swagger2配置显示及修改描述

需求描述 项目接口文档使用yapi来进行管理,原来的controller仅使用了一个@Api的注解,且注解的描述是controller类名,添加@ApiOperation、@ApiModel和@ApiModelProperty后,第一次生成接口-接口列表下的分组是现在@Api配置的名称,业务和产品要看这个接口,显示controller类…

R语言生存分析(机器学习)(2)——Enet(弹性网络)

弹性网络&#xff08;Elastic Net&#xff09;:是一种用于回归分析的统计方法&#xff0c;它是岭回归&#xff08;Ridge Regression&#xff09;和lasso回归&#xff08;Lasso Regression&#xff09;的结合&#xff0c;旨在克服它们各自的一些限制。弹性网络能够同时考虑L1正则…

解析TCP/IP协议的分层模型:探寻网络通信的精髓

了解ISO模型&#xff1a;构建通信的蓝图 为了促进网络应用的普及&#xff0c;国际标准化组织&#xff08;ISO&#xff09;引入了开放式系统互联&#xff08;Open System Interconnect&#xff0c;OSI&#xff09;模型。这个模型包括了七个层次&#xff0c;从底层的物理连接到顶…

图像变形之移动最小二乘算法(MLS)

基本原理 基于移动最小二乘的图像变形是通过一组源控制点和目标控制点来控制变形&#xff0c;对于每一个待求变形后位置的点而言&#xff0c;根据预设的形变类型&#xff08;如仿射变换、相似变换、刚性变换&#xff09;求解一个最小二乘优化目标函数估计一个局部的坐标变换矩阵…

leetcode 力扣刷题 旋转矩阵(循环过程边界控制)

力扣刷题 旋转矩阵 二维矩阵按圈遍历&#xff08;顺时针 or 逆时针&#xff09;遍历59. 旋转矩阵Ⅱ54. 旋转矩阵剑指 Offer 29. 顺时针打印矩阵 二维矩阵按圈遍历&#xff08;顺时针 or 逆时针&#xff09;遍历 下面的题目的主要考察点都是&#xff0c;二维数组从左上角开始顺…

用Node.js吭哧吭哧撸一个运动主页

简单唠唠 某乎问题&#xff1a;人这一生&#xff0c;应该养成哪些好习惯&#xff1f; 问题链接&#xff1a;https://www.zhihu.com/question/460674063 如果我来回答肯定会有定期运动的字眼。 平日里也有煅练的习惯&#xff0c;时间久了后一直想把运动数据公开&#xff0c;…

Vue基本知识

一、vue入门 Vue为前端的框架&#xff0c;免除了原生js的DOM操作。简化书写。 基于MVVM的思想&#xff0c;实现数据的双向绑定&#xff0c;使编程的重点放在数据上。 1、引入vue.js文件 2、定义vue核心对象&#xff0c;定义数据模型 3、编写视图 //1、引入vue.js <scr…

【学习心得】安装cuda/cudann和pytorch

一、查看驱动信息 # 进入CMD输入命令 nvidia-smi 也可以右下角图标打开NVIDIA 设置进行查看 二、下载安装CUDA 1、下载 下载地址 https://developer.nvidia.com/ 2、安装 推荐自定义安装。建议只勾选Cuda&#xff0c;只安装这一个就好&#xff0c;以免报错安装失败。 3、验证…

05 - 研究 .git 目录

查看所有文章链接&#xff1a;&#xff08;更新中&#xff09;GIT常用场景- 目录 文章目录 1. HEAD2. config3. refs4. objects 1. HEAD 2. config 3. refs 4. objects Git对象一共有三种&#xff1a;数据对象 blob、树对象 tree以及提交对象 commit&#xff0c;这些对象都被保…

小白到运维工程师自学之路 第七十四集 (kubernetes基于calico部署应用nginx)

一、详细介绍calico Calico 是一种基于 BGP 的、纯三层的、容器间互通的网络方案。与 OpenStack、Kubenetes、AWS、GCE 等云平台都能够良好的集成。在虚拟化平台中&#xff0c;如 OpenStack、Docker 等都需要实现 workloads 之间互连&#xff0c;但同时也需要对容器做隔离控制…

梅赛德斯-奔驰将成为首家集成ChatGPT的汽车制造商

ChatGPT的受欢迎程度毋庸置疑。OpenAI这个基于人工智能的工具&#xff0c;每天能够吸引无数用户使用&#xff0c;已成为当下很受欢迎的技术热点。因此&#xff0c;有许多公司都在想方设法利用ChatGPT来提高产品吸引力&#xff0c;卖点以及性能。在汽车领域&#xff0c;梅赛德斯…

抓包工具Fiddler下载与安装

一、Fiddler介绍 1.Fiddler简介 Fiddler 是一款免费、灵活、操作简单、功能强大的 HTTP 代理工具&#xff0c;是目前最常用的 HTTP 抓包工具之一。可以抓取所有的 HTTP/HTTPS 包、过滤会话、分析请求详细内容、伪造客户端请求、篡改服务器响应、重定向、网络限速、断点调试等…

GPT-4 如何为我编写测试

ChatGPT — 每个人都在谈论它,每个人都有自己的观点,玩起来很有趣,但我们不是在这里玩— 我想展示一些实际用途,可以帮助您节省时间并提高效率。 我在本文中使用GPT-4 动机 我们以前都见过这样的情况——代码覆盖率不断下降的项目——部署起来越来越可怕,而且像朝鲜一样…

POJ 2429 Miller-rabin素数判定 + pollard-rho质因子分解 + 埃氏筛法

题目不能说是很难&#xff0c;只是用到了许多数学上的知识&#xff08;费马小定理&#xff0c;miller-radin&#xff0c;pollard-rho&#xff09;&#xff0c;还有一些算法上的知识DFS&#xff0c;辗转相除。 我也很菜&#xff0c;一个周末的时间都用在这个题目上了&#xff0…

软考第二章 信息技术发展

本章内容&#xff1a;软件硬件、网络、存储、新技术。 文章目录 2.1 信息技术及其发展2.1.1 计算机硬件2.1.2 计算机网络2.1.3 存储和数据库2.1.4 信息安全 2.2 新一代信息技术2.2.1 物联网2.2.2 云计算2.2.3 大数据2.2.4 区块链2.2.5 人工智能虚拟现实 2.1 信息技术及其发展 …

EXCEL按列查找,最终返回该列所需查询序列所对应的值,VLOOKUP函数

EXCEL按列查找&#xff0c;最终返回该列所需查询序列所对应的值 示例&#xff1a;国标行业分类汉字&#xff0c;匹配id 使用VLOOKUP函数 第一参数&#xff1a;拿去查询的值。 第二参数&#xff1a;匹配的数据。 Ps&#xff1a;Sheet1!$C 21 : 21: 21:E 117 &#xff0c;需要…

通过版本号控制强制刷新浏览器或清空浏览器缓存

背景介绍 在我们做 web 项目时&#xff0c;经常会遇到一个问题就是&#xff0c;需要 通知业务人员&#xff08;系统用户&#xff09;刷新浏览器或者清空浏览器 cookie 缓存的情况。 而对于用户而言&#xff0c;很多人一方面不懂如何操作&#xff0c;另一方面由于执行力问题&am…

屏蔽socket 实例化时,握手阶段报错信息WebSocket connection to ‘***‘ failed

事情起因是这样的&#xff1a; 我们网站是需要socket链接实行实时推送服务&#xff0c;有恶意竞争对手通过抓包或者断网&#xff0c;获取到了我们的socket链接地址&#xff0c;那么他就可以通过java写一个脚本无限链接这个socket地址。形成dos攻击。使socket服务器资源耗尽&…