Vue组件之间的通讯方式(父传子、子传父、兄弟组件间传值、非父子组件间传值)

本文主要是介绍Vue组件之间的通讯方式(父传子、子传父、兄弟组件间传值、非父子组件间传值),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Vue组件之间的通讯方式(父传子、子传父、兄弟组件间传值)

*引子

  1. 首先,我们初步建立一个以vue/cli4为基础的项目;
  2. 在components的文件夹下新建Parent.vue和ChildOne的父组件和子组件;
  3. 在App.vue和Parent.vue中映射成组件标签。

基本结构如下:
Parent.vue

<template><div><h1>Parent</h1><child-one></child-one></div>
</template><script>
import ChildOne from '@/components/ChildOne'
export default {data () {return {}},components:{ChildOne}
}
</script>

ChildOne.vue

<template><div><h1>ChildOne</h1></div>
</template><script>
export default {
};
</script>

一、父传子

  • Props属性传递
    父组件通过自定义属性给子组件传值,子组件用props接收

代码如下

Parent.vue

//template
<div><h1>Parent</h1><child-one :msgToChild="msg"></child-one>
</div>//script  
data () {return {msg:'i am you father'}
},

ChildOne.vue

//template 
<div><h1>ChildOne</h1><div>接收到父亲传来的消息:{{msgToChild}}</div>
</div>//script
export default {//第一种写法// props:['msgToChild']//第二种写法props: {msgToChild: {type: String,}}
};
  • 方法传递
    通过组件标签进行方法的传递,子组件$emit触发方法

Parent.vue

//template 
<!--进行方法的传递-->
<child-one @methodToChild="showMsg"></child-one>//script   
methods:{/*定义方法*/showMsg () {alert('i am your father')}
},

ChildOne.vue

//tempalte<div>接收到父亲传来的消息:{{msgToChild}}</div><!--定义一个按钮用来触发方法--><button @click="needFatherMethod">place click me</button>//script   props:{/*接收方法*/methodToChild:{type:Function}},methods:{/*触发方法*/needFatherMethod () {this.$emit('methodToChild')}}
  1. 通过parent获取方法和属性
    通过$parent来获取父组件的实例,从而获取父组件的属性和方法

子组件:ChildOne.vue

//template   <!--新建一个按钮来触发方法--><button @click="$parentMethod">place $parent</button>/*定义后去父组件实例的方法*/$parentMethod (){// console.log(this.$parent._data.msg)//i am you fatherconsole.log(this.$parent.msg)//i am you fatherthis.$parent.showMsg()//调用方法}

二、子传父

1、 属性传递
通过触发父组件的方法进行传递数据(这等同于父 --> 子 传递方法,方法的参数就是子组件的数据,emit的第二个参数就是父组件想要的数据)

缺点

  • 需要一定的触发条件
  • 不是响应式数据
  • 一般触发条件只能在子组件,因为要得到的是子组件的数据(比如说在父函数定义一个方法通过这种方式来的到子组件数据,似乎比较困难。但是可以通过生命周期函数在子组件触发来传递数据)

父组件:Parent.vue

//template
<div>接收到子组件传来的消息: {{childMsg}}</div>
<!--进行方法的传递-->
<child-one @getChildMsg="getChildMsg"></child-one>//scriptdata () {return {childMsg:''}},/*1.定义得到子组件数据的方法,触发条件只能在子组件* 2.在data中定义一个属性来保存子组件传递过来的数据* */getChildMsg (childMsg){this.childMsg = childMsg},

子组件:ChildOne.vue

//template
<!--定义向父组件信息的触发的条件--><button @click="setParentMsg">place send parent msg</button>
//script   data (){return {/*子组件数据*/msg:'i am your child'}},/*触发父组件的方法,并传递参数*/setParentMsg (){this.$emit('getChildMsg',this.msg)},
  1. 通过$refs主动获取子组件方法和属性
    通过ref得到子组件的实例,进而得到子组件的方法和属性

父组件:Parent.vue

//template
<button @click="getMyChildMsgAndMethod">作为父亲,我要主动拿到孩子的信息</button>
<div>这是孩子的信息: {{childMsg}}</div><!--通过ref得到子组件的实例--><child-one ref="myChild"></child-one>
//scriptdata () {return {childMsg:''}},/*得到子组件的方法和属性*/getMyChildMsgAndMethod (){this.childMsg = this.$refs.myChild.msgthis.$refs.myChild.methodToParent()},

子组件:ChildOne.vue

//script   
/*父亲调用的方法*/methodToParent (){alert('i am you child')},
  1. 通过children主动获取子组件方法和属性
    通过this.$ children得到的是一个子组件实例的数组,除此之外,他的用法几乎和$refs相同

父组件:Parent.vue

//template <button @click="$childrenMsg">$children得到孩子信息</button><div>这是孩子的信息: {{childMsg}}</div>
//script$childrenMsg (){/*this.$children得到是一个数组*/const child = this.$children[0]this.childMsg = child.msgchild.methodToParent()},

三、兄弟间的通讯

  1. 通过共同的父亲进行传递信息
    父组件只充当邮递员的角色,他所利用的就是,父子和子父之间的通讯,两者的结合
    在components文件夹下,新建ChildTwo.vue文件,代码如下

子组件two:ChildTwo.vue

//template
<template><div><h1>ChildTwo</h1><div>{{commonMsg}}</div></div>
</template>
//script   export default {props:['common-msg'],name: "ChildTwo",}

子组件one:ChildOne.vue

//template <!--向兄弟组件传递数据--><button @click="setBrotherMsg">One send brother Two a msg</button>
//script  data (){return {/*定义数据*/commonMsg:'I miss you ,my brother!'}},props:{//接收父亲传来的方法,主要用于拿到此组件的数据poster:{type:Function},},/*调用方法传递数据*/setBrotherMsg (){//把数据传给父组件this.$emit('poster',this.commonMsg)},

父组件:Parent.vue

//template  <!--进行方法的传递--><child-one @poster="poster">从One拿数据存储到commonMsg</child-one><!--数据传递--><child-two :common-msg="commonMsg">把commonMsg的数据给Two</child-two>
//script   data () {return {//定义保存数据的变量commonMsg:''}},methods:{/*定义拿到数据的方法*/poster (commonMsg){this.commonMsg = commonMsg},}
  1. 全局事件总线—EventBus
    EventBus相当于全局的 $ emit、$ on,我们需要把它放到一个所有组件都能看得到的地方,
    eventBus原理就是利用和 emit 并实例化一个全局 vue 实现数据共享
//main.jsVue.prototype.$bus=new Vue()
//传值组件this.$bus.$emit('eventTarget','值') 
//接收组件this.$bus.$on('eventTarget',value=> console.log(value))
  1. 过PubSub通讯
    PubSub是一个包,专门用于组件之间的通讯
  • 使用PubSub.subsribe()订阅(注册)事件
  • 使用PubSub.publish()触发事件
  • 他与event-bus的使用差不多,只是参数略有不同,绑定事件的第一个参数必须传(请看下面的例题) 一般在React中用的较多

使用方法

1.下载

npm install pubsub-js --save

2.在ChildOne.vue引入

兄弟组件:ChildOne.vue

//template
<button @click="pubsubBrotherMsg">send brother msg by pubsub</button>
//script
import PubSub from 'pubsub-js'methods: {pubsubBrotherMsg (){PubSub.subscribe('pubsubMsg',this.commonMsg)},}

2.在ChildTwo.vue引入

兄弟组件:ChildTwo.vue

import PubSub from 'pubsub-js'data(){return {pubsubMsg:''}},mounted() {/*msg:回调函数第一个参数,必须传*/PubSub.subscribe('pubsubMsg',(msg,data) => {this.pubsubMsg = data} )}
  1. 通过Vuex通讯
    Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。vuex使用手册

四、非父子组件间传值

  1. 通过Vuex通讯
    vuex 是通过将 state 作为数据中心、各个组件共享 state 实现跨组件通信的。
    vuex 就是一个仓库,仓库里放了很多对象。其中 state 就是数据源存放地,对应于一般 vue 对象里面的 data 里面存放的数据是响应式的,vue 组件从store读取数据,若是 store 中的数据发生改变,依赖这相数据的组件也会发生更新它通过 mapState 把全局的 stategetters 映射到当前组件的 computed 计算属性。vuex 更多地用于解决跨组件通信以及作为数据中心集中式存储数据
    vuex核心概念图

*五个核心概念简单介绍:

  • state
    Vuex里的state相当于一个全局的state,你可以在component的任何地方获取和修改它。
//获取state
this.$store.state.count//vuex的辅助方法
import { mapState } from 'vuex'
computed:mapState(['count'
])
  • getters
    Vuex里的getters类似于computed,就像计算属性一样,getter 的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算。
//直接使用
this.$store.getters.doneTodosCount//使用辅助方法
import { mapGetters } from 'vuex'
computed:mapGetters({doneCount: 'doneTodosCount'
})
  • mutations
    更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。一条重要的原则就是要记住 mutation 必须是同步函数
//触发mutations
this.$store.commit('xxx')//辅助函数
import { mapMutations } from 'vuex'
methods:mapMutations(['increment' ])

 在increment函数中调用setTimeout()方法在2s后更新count,这就是一个异步调用。例如:

const store = new Vuex.Store({state: {count: 0},mutations: {increment (state) {setTimeout( () => {state.count++}, 2000)}}
})

 Vuex 的 store 中的状态是响应式的,那么当我们变更状态时,监视状态的 Vue 组件也会自动更新。这也意味着 Vuex 中的 mutation 也需要与使用 Vue 一样遵守一些注意事项:
1.最好提前在你的 store 中初始化好所有所需属性。
2.当需要在对象上添加新属性时,你应该:
(1)使用 Vue.set(obj, 'newProp', 123), 或者
(2)以新对象替换老对象。例如,利用对象展开运算符 (opens new window)我们可以这样写:

state.obj = { ...state.obj, newProp: 123 }
  • actions
    类似于 mutation,不同在于:
    Action 提交的是 mutation,而不是直接变更状态,Action 可以包含任意异步操作
//触发action
store.dispatch('increment')//辅助函数
import { mapActions } from 'vuex'
methods:mapActions(['increment' ])
  • Module
    由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块——从上至下进行同样方式的分割。
const moduleA = {state: { ... },mutations: { ... },actions: { ... },getters: { ... }
}const moduleB = {state: { ... },mutations: { ... },actions: { ... }
}const store = new Vuex.Store({modules: {a: moduleA,b: moduleB}
})store.state.a // -> moduleA 的状态
store.state.b // -> moduleB 的状态

详情理解:vuex五个核心概念https://juejin.cn/post/7196924295309213752

对于大型应用,我们会希望把 Vuex 相关代码分割到模块中。下面是项目结构示例:

highlighter- Bash
└── store├── index.js          # 我们组装模块并导出 store 的地方├── actions.js        # 根级别的 action├── mutations.js      # 根级别的 mutation└── modules├── cart.js       # 购物车模块└── products.js   # 产品模块

这篇关于Vue组件之间的通讯方式(父传子、子传父、兄弟组件间传值、非父子组件间传值)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/168919

相关文章

gradle第三方Jar包依赖统一管理方式

《gradle第三方Jar包依赖统一管理方式》:本文主要介绍gradle第三方Jar包依赖统一管理方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录背景实现1.顶层模块build.gradle添加依赖管理插件2.顶层模块build.gradle添加所有管理依赖包

Linux之systemV共享内存方式

《Linux之systemV共享内存方式》:本文主要介绍Linux之systemV共享内存方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、工作原理二、系统调用接口1、申请共享内存(一)key的获取(二)共享内存的申请2、将共享内存段连接到进程地址空间3、将

Maven中引入 springboot 相关依赖的方式(最新推荐)

《Maven中引入springboot相关依赖的方式(最新推荐)》:本文主要介绍Maven中引入springboot相关依赖的方式(最新推荐),本文给大家介绍的非常详细,对大家的学习或工作具有... 目录Maven中引入 springboot 相关依赖的方式1. 不使用版本管理(不推荐)2、使用版本管理(推

C#使用StackExchange.Redis实现分布式锁的两种方式介绍

《C#使用StackExchange.Redis实现分布式锁的两种方式介绍》分布式锁在集群的架构中发挥着重要的作用,:本文主要介绍C#使用StackExchange.Redis实现分布式锁的... 目录自定义分布式锁获取锁释放锁自动续期StackExchange.Redis分布式锁获取锁释放锁自动续期分布式

Java对象转换的实现方式汇总

《Java对象转换的实现方式汇总》:本文主要介绍Java对象转换的多种实现方式,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录Java对象转换的多种实现方式1. 手动映射(Manual Mapping)2. Builder模式3. 工具类辅助映

Spring Boot读取配置文件的五种方式小结

《SpringBoot读取配置文件的五种方式小结》SpringBoot提供了灵活多样的方式来读取配置文件,这篇文章为大家介绍了5种常见的读取方式,文中的示例代码简洁易懂,大家可以根据自己的需要进... 目录1. 配置文件位置与加载顺序2. 读取配置文件的方式汇总方式一:使用 @Value 注解读取配置方式二

JAVA保证HashMap线程安全的几种方式

《JAVA保证HashMap线程安全的几种方式》HashMap是线程不安全的,这意味着如果多个线程并发地访问和修改同一个HashMap实例,可能会导致数据不一致和其他线程安全问题,本文主要介绍了JAV... 目录1. 使用 Collections.synchronizedMap2. 使用 Concurren

C# foreach 循环中获取索引的实现方式

《C#foreach循环中获取索引的实现方式》:本文主要介绍C#foreach循环中获取索引的实现方式,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录一、手动维护索引变量二、LINQ Select + 元组解构三、扩展方法封装索引四、使用 for 循环替代

将Java程序打包成EXE文件的实现方式

《将Java程序打包成EXE文件的实现方式》:本文主要介绍将Java程序打包成EXE文件的实现方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录如何将Java程序编程打包成EXE文件1.准备Java程序2.生成JAR包3.选择并安装打包工具4.配置Launch4

springboot上传zip包并解压至服务器nginx目录方式

《springboot上传zip包并解压至服务器nginx目录方式》:本文主要介绍springboot上传zip包并解压至服务器nginx目录方式,具有很好的参考价值,希望对大家有所帮助,如有错误... 目录springboot上传zip包并解压至服务器nginx目录1.首先需要引入zip相关jar包2.然