Vue组件间如何通信(vue,编程语言)

时间:2024-05-07 03:35:24 作者 : 石家庄SEO 分类 : 编程语言
  • TAG :

'
}
},
mounted(){
this.bookLists=this.$parent.books
}
}
</script>

注意:&dollar;parent拿到的是对象,如果是最顶层没有父组件的情况下拿到的是undefined$children拿到的是数组,如果是做底层没有子组件的情况下,拿到的是空数组;这两种通信方式只能用于父子组件通信

三、ref

ref如果在普通Dom元素上使用,引用指向的就是 DOM 元素;如果在子组件上使用,引用就指向组件实例,可以通过实例直接调用组件的方法和数据

//父组件parent.vue
<template>
<div>
<Childref="child"/>
<button@click="getChildData">获取子组件数据</button>
</div>
</template>

<script>
importChildfrom'./components/Child.vue'

exportdefault{
name:'parent',
components:{
Child
},
methods:{
getChildData(){
constmsg=this.$refs['child'].msg
console.log(msg)
this.$refs['child'].say()
}
}
}
</script>

//子组件child.vue
<script>
exportdefault{
name:'child',
data(){
return{
msg:'我是子组件的值!'
}
},
methods:{
say(){
alert('你好,我是子组件!')
}
},
}
</script>

四、provide/inject

祖先组件通过provide来提供变量,子孙组件通过inject注入变量来获取祖先组件的数据,不管子孙组件嵌套有多深, 只要调用了inject 那么就可以注入provide中的数据。下面是具体代码:

//父组件
<template>
<div>
<h2>康熙</h2>
<Son/>
</div>
</template>

<script>
importSonfrom'./components/Son.vue'

exportdefault{
components:{
Son
},
provide(){
return{
FatherToSon:this.FatherToSon,
FatherToGrandson:this.FatherToGrandson,
}
},
data(){
return{
FatherToSon:'我是康熙,雍正,你是我儿子!',
FatherToGrandson:'我是康熙,乾隆,你是我孙子!',
}
}
}
</script>

//子组件
<template>
<div>
<h2>雍正</h2>
<button@click="receive">接收</button>
<Grandson/>
</div>
</template>

<script>
importGrandsonfrom'./Grandson.vue'
exportdefault{
components:{
Grandson
},
inject:['FatherToSon'],
methods:{
receive(){
alert(this.FatherToSon)
}
}
}
</script>

//孙组件
<template>
<div>
<h2>乾隆</h2>
<button@click="receive">接收</button>
</div>
</template>

<script>
exportdefault{
inject:['FatherToGrandson'],
methods:{
receive(){
alert(this.FatherToGrandson)
}
}
}
</script>

Vue组件间如何通信
注意:provide/inject只能从上往下传值,且不是响应式,若要变成响应式的数据provide需要提供函数

五、eventBus&dollar;emit/$on

eventBus是消息传递的一种方式,基于一个消息中心,订阅和发布消息的模式,称为发布订阅者模式。
eventBus 又称为事件总线。在 Vue 中可使用 eventBus 来作为沟通桥梁的概念,就像是所有组件共用相同的事件中心,可向该中心注册发送事件或接收事件,所以组件都可以上下平行地通知其他组件。

  • $emit('name',args): name:发布的消息名称 , args:发布的消息

  • $on('name',fn): name:订阅的消息名称, fn: 订阅的消息

  • &dollar;once('name',fn): name:订阅的消息名称, fn: 订阅的消息。与$on相似但是只触发一次,一旦触发之后,监听器就会被移除

  • &dollar;off('name',callback):name:事件名称,callback:回调监听器
    eventbus可以实现任何组件之前的通信,下面以兄弟组件为例

    1、初始化,全局引入
//main.js
//全局添加事件总线
Vue.prototype.$bus=newVue()
2、发送事件

在parent.vue引入ChildA和ChildB组件,使它们成为兄弟组件

//父组件parent.vue
<template>
<div>
<ChildA/>
<ChildB/>
</div>
</template>

<script>
importChildAfrom'./components/childA'
importChildBfrom'./components/childB'
exportdefault{
components:{
ChildA,
ChildB
}
}
</script>

在ChildA组件中用$emit发送事件

//ChildA组件
<template>
<div>
<h2>组件A</h2>
<button@click="send">发送</button>
</div>
</template>

<script>
exportdefault{
methods:{
//发送事件
send(){
this.$bus.$emit('message','欢迎使用eventBus!')
}
}
}
</script>

3、接收事件发送的事件

在ChildB组件中用$on接收ChildA发送的事件

//ChildB组件
<template>
<div>
<h2>组件B</h2>
</div>
</template>

<script>
exportdefault{
mounted(){
//接收事件
this.$bus.$on('message',data=>{
alert('我是组件B,我收到的消息为:'+data)
})
},
beforeDestroy(){
this.$bus.$off('message')
}
}
</script>

注意:&dollar;on监听的事件不会自动移除监听,因此在不用时最好使用$off移除监听以免产生问题

六、&dollar;attrs/$listeners

1、简介

当组件为两级嵌套时,一般采用props&dollar;emit,但遇到多级组件嵌套时这种方法就不太适用了,如果不做中间处理,只传递数据用vuex有点大材小用了。因此在vue2.4中为了解决这一需求,便引入了&dollar;attrs$listeners, 新增了inheritAttrs属性

  • &dollar;attrs:当父组件传递了很多数据给子组件时,子组件没有声明props来进行接收,么子组件中的attrs属性就包含了所有父组件传来的数据(除开已经props声明了的);子组件还可以使用v−bind="$attrs"的形式将所有父组件传来的数据(除开已经props声明了的)传向下一级子组件,通常和interitAttrs属性一起使用。

  • &dollar;listeners:包含了父组件中(不含.native修饰器的)v-on 事件监听器,通过v-on="$listeners",可以将这些事件绑定给它自己的子组件

    2、实例

    下面看一个例子:

//父组件
<template>
<div>
<ChildA:name="name":sex="sex":age="age"@getName="getName"@getAge="getAge"/>
</div>
</template>

<script>
importChildAfrom'./components/childA'
exportdefault{
name:'parent',
components:{
ChildA,
},
data(){
return{
name:'小明',
age:18,
sex:'男'
}
},
methods:{
//获取名字
getName(){
console.log('我的名字是'+this.name)
},
//获取年龄
getAge(){
console.log('我今年'+this.age+'岁');
}
}
}
</script>

//子组件A
<template>
<div>
<h2>组件A</h2>
{{msgA}}
<hr/>
<ChildBv-bind="$attrs":height="height"v-on="$listeners"@getHeight="getHeight"/>
</div>
</template>

<script>
importChildBfrom'./childB.vue'
exportdefault{
name:'ChildA',
components:{
ChildB
},
data(){
return{
msgA:null,
height:'175cm'
}
},
props:{
sex:{
type:String,
default:''
}
},
mounted(){
this.msgA=this.$attrs
console.log('组件A获取的$listeners:',this.$listeners)
},
methods:{
//获取身高
getHeight(){
console.log('我的身高是'+this.height);
}
}
}
</script>

//孙组件B
<template>
<div>
<h2>组件B</h2>
{{msgB}}
</div>
</template>

<script>
exportdefault{
name:'ChildB',
data(){
return{
msgB:null
}
},
mounted(){
this.msgB=this.$attrs
console.log('组件B获取的$listeners:',this.$listeners)
}
}
</script>

$attrs获取的结果:
Vue组件间如何通信
$listeners获取的结果:

Vue组件间如何通信

如代码和图所示组件A中props声明接收了sex属性,因此组件中&dollar;attrs获取的是父组件中绑定的除去sex属性的值;组件A中使用了v-bind="&dollar;attrs"v-on="$listeners",则组件B获取不仅是组件A中本身绑定的属性和方法还包含组件A获取父组件绑定的属性和方法

3、inheritAttrs

如果父组件传递了很多参数给子组件,而子组件没有用props完全接收,那么没有接收的这些属性作为普通的 HTML attribute 应用在子组件的根元素上
如果你不希望子组件的根元素继承特性,你可以在组件的选项中设置inheritAttrs: false

以上面的组件B为例,当inheritAttrs为true(inheritAttrs默认为true)
Vue组件间如何通信

当inheritAttrs为false时

//孙组件B
exportdefault{
name:'ChildB',
inheritAttrs:false,
data(){
return{
msgB:null
}
},
mounted(){
this.msgB=this.$attrs
console.log('组件B获取的$listeners:',this.$listeners)
}
}

Vue组件间如何通信

七、Vuex

1、Vuex概述

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式 + 库。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
状态管理包含以下几个部分:
Vue组件间如何通信

  • 状态(State),驱动应用的数据源

  • 视图(View),以声明方式将状态映射到视图;

  • 操作(Actions),响应在视图上的用户输入导致的状态变化

视图发生变化会导致数据源的改变,数据源发生变化则会改变视图,则上面表示是一个“单向数据流”。但是当我们的应用遇到多个组件共享状态时,单向数据流的简洁性很容易被破坏:

  • 多个视图依赖于同一状态。

  • 来自不同视图的行为需要变更同一状态。

因此,为了解决这种问题我们把组件的共享状态抽取出来,以一个全局单例模式管理。在这种模式下,我们的组件树构成了一个巨大的“视图”,不管在树的哪个位置,任何组件都能获取状态或者触发行为!

通过定义和隔离状态管理中的各种概念并通过强制规则维持视图和状态间的独立性,我们的代码将会变得更结构化且易维护。
Vue组件间如何通信

2、 Vuex各个模块

1、state:存储应用中需要共享的状态,是Vuex中的唯一数据源。
2、getters:类似Vue中的计算属性computedgetter 的返回值会根据它的依赖被缓存起 来,且只有当它的依赖值发生了改变才会被重新计算。
3、mutations:更改 Vuex 的 store 中的状态(state)的唯一方法,且mutation 必须是同步函数
4、actions:类似于 mutation,提交的是 mutation,而不是直接变更状态;可以包含任意异步操作
5、modules:将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块——从上至下进行同样方式的分割

3、Vuex举例

//父组件
<template>
<divclass="home">
<h2>父组件</h2>
<hr/>
<ChildA/>
<hr/>
<ChildB/>
</div>
</template>

<script>
importChildAfrom'./components/ChildA'
importChildBfrom'./components/ChildB'

exportdefault{
name:'parent',
components:{
ChildA,
ChildB
}
}
</script>

//子组件A
<template>
<div>
<h2>组件A</h2>
<p>A获取的值:{{count}}</p>
<button@click="add(5)">ChildA-add</button>
</div>
</template>

<script>
exportdefault{
computed:{
count(){
returnthis.$store.state.count
}
},
methods:{
//改变store里count的值
add(num){
this.$store.dispatch('countAdd',num)
}
}
}
</script>

<style>

</style>

//子组件B
<template>
<div>
<h2>组件B</h2>
<p>B获取的值:{{countB}}</p>
<button@click="add(10)">ChildB-add</button>
</div>
</template>

<script>
import{mapMutations,mapGetters}from'vuex'
exportdefault{
computed:{
...mapGetters({
countB:'getCount'
})
},
methods:{
...mapMutations(['countAdd']),
//改变store里count的值
add(num){
this.countAdd(num)
}
}
}
</script>

<style>

</style>

store.js

importVuefrom'vue'
importVuexfrom'vuex'

Vue.use(Vuex)

exportdefaultnewVuex.Store({
state:{
count:0,
},
getters:{
getCount:(state)=>{
returnstate.count
}
},
mutations:{
countAdd(state,num){
state.count+=num
}
},
actions:{
countAdd(context,num){
context.commit('countAdd',num)
}
},
modules:{
}
})

Vue组件间如何通信

八、localStorage/sessionStorage

1、介绍

localStorage:本地存储对象,存储的数据是永久性数据,页面刷新,即使浏览器重启,除非主动删除不然存储的数据会一直存在
sessionStorage:与localStorage相似,但是只有在当前页面下有效,关闭页面或浏览器存储的数据将会清空

localStorage和sessionStorage常用的API:

setItem(key,value)——保存数据,以键值对的方式储存信息。
getItem(key)——获取数据,将键值传入,即可获取到对应的value值。
removeItem(key)——删除单个数据,根据键值移除对应的信息。
clear()——删除所有的数据
key(index)——获取某个索引的key
2、举例
//存储
setItem(){
window.localStorage.setItem('name1','小明')
window.sessionStorage.setItem('name2','小红')
}
//接收
receive(){
constname1=window.localStorage.getItem('name1')
constname2=window.sessionStorage.getItem('name2')
console.log(name1)//打印结果为:小明
console.log(name2)//打印结果为:小红
}
3、setItem()和getItem()使用时的类型转换

localStorage和sessionStorage通过setItem()存储数据会自动转换为String类型,但是通过getItem()其类型并不会转换回来(localStorage和sessionStorage使用方法一样,下面均以localStorage为例)

constnum=1
window.localStorage.setItem('num',num)

constnumRec=window.localStorage.getItem('num')
console.log(numRec,typeof(numRec))//1string

因此正确的存储方式应该为:存储之前用JSON.stringify()方法将数据转换成json字符串形式;需要使用数据的时候用JSON.parse()方法将之前存储的字符串转换成json对象

constnum=1
window.localStorage.setItem('num',JSON.stringify(num))
constobj={
name:'小红',
age:18
}
window.localStorage.setItem('obj',JSON.stringify(obj))

constnumRec=JSON.parse(window.localStorage.getItem('num'))
console.log(numRec,typeof(numRec))//1'number'
constobjRec=JSON.parse(window.localStorage.getItem('obj'))
console.log(objRec,typeof(objRec))//{name:'小红',age:18}'object'

注意:localStorage.setItem()和sessionStorage.setItem()不能直接存储对象,必须使用JSON.stringify()JSON.parse()转换实现

总结

以上8种通信方式主要应用在以下三类场景:

  • 父子组件通信:最经常使用通信方式的是props/&dollar;emit,单一的父子组件通信使用&dollar;parent>/&dollar;children也比较方便;父组件也常使用ref获取子组件实例;也可使用provide/inject&dollar;attrs/&dollar;listeners以及localStorage/sessionStorage

  • 兄弟组件通信:简单的数据传递可使用eventBus&dollar;emit/&dollar;on;复杂的数据使用Vuex比较方便;也可以使用localStorage/sessionStorage;

  • 跨级组件通信:父子孙等嵌套组件通信方式多使用provide/inject&dollar;attrs/&dollar;listeners;跨级组件通信的数据如果不复杂可使用eventBuslocalStorage/sessionStorage;如果数据复杂可使用Vuex,但是要注意刷新界面Vuex存储的数据会消失

这里是亿速云网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

本文:Vue组件间如何通信的详细内容,希望对您有所帮助,信息来源于网络。
上一篇:LyScript如何实现绕过反调试保护下一篇:

23 人围观 / 0 条评论 ↓快速评论↓

(必须)

(必须,保密)

阿狸1 阿狸2 阿狸3 阿狸4 阿狸5 阿狸6 阿狸7 阿狸8 阿狸9 阿狸10 阿狸11 阿狸12 阿狸13 阿狸14 阿狸15 阿狸16 阿狸17 阿狸18