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组件之间的通讯方式(父传子、子传父、兄弟组件间传值、非父子组件间传值)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!


原文地址:https://blog.csdn.net/cxywxy666/article/details/128949829
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.chinasem.cn/article/168919

相关文章

JAVA封装多线程实现的方式及原理

《JAVA封装多线程实现的方式及原理》:本文主要介绍Java中封装多线程的原理和常见方式,通过封装可以简化多线程的使用,提高安全性,并增强代码的可维护性和可扩展性,需要的朋友可以参考下... 目录前言一、封装的目标二、常见的封装方式及原理总结前言在 Java 中,封装多线程的原理主要围绕着将多线程相关的操

kotlin中的行为组件及高级用法

《kotlin中的行为组件及高级用法》Jetpack中的四大行为组件:WorkManager、DataBinding、Coroutines和Lifecycle,分别解决了后台任务调度、数据驱动UI、异... 目录WorkManager工作原理最佳实践Data Binding工作原理进阶技巧Coroutine

Golang中拼接字符串的6种方式性能对比

《Golang中拼接字符串的6种方式性能对比》golang的string类型是不可修改的,对于拼接字符串来说,本质上还是创建一个新的对象将数据放进去,主要有6种拼接方式,下面小编就来为大家详细讲讲吧... 目录拼接方式介绍性能对比测试代码测试结果源码分析golang的string类型是不可修改的,对于拼接字

Linux下修改hostname的三种实现方式

《Linux下修改hostname的三种实现方式》:本文主要介绍Linux下修改hostname的三种实现方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录linux下修改ho编程stname三种方式方法1:修改配置文件方法2:hFvEWEostnamectl命

SpringBoot接收JSON类型的参数方式

《SpringBoot接收JSON类型的参数方式》:本文主要介绍SpringBoot接收JSON类型的参数方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、jsON二、代码准备三、Apifox操作总结一、JSON在学习前端技术时,我们有讲到过JSON,而在

Spring Security注解方式权限控制过程

《SpringSecurity注解方式权限控制过程》:本文主要介绍SpringSecurity注解方式权限控制过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、摘要二、实现步骤2.1 在配置类中添加权限注解的支持2.2 创建Controller类2.3 Us

SpringBoot操作MaxComputer方式(保姆级教程)

《SpringBoot操作MaxComputer方式(保姆级教程)》:本文主要介绍SpringBoot操作MaxComputer方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的... 目录引言uqNqjoe一、引入依赖二、配置文件 application.properties(信息用自己

Java中数组转换为列表的两种实现方式(超简单)

《Java中数组转换为列表的两种实现方式(超简单)》本文介绍了在Java中将数组转换为列表的两种常见方法使用Arrays.asList和Java8的StreamAPI,Arrays.asList方法简... 目录1. 使用Java Collections框架(Arrays.asList)1.1 示例代码1.

java两个List的交集,并集方式

《java两个List的交集,并集方式》文章主要介绍了Java中两个List的交集和并集的处理方法,推荐使用Apache的CollectionUtils工具类,因为它简单且不会改变原有集合,同时,文章... 目录Java两个List的交集,并集方法一方法二方法三总结java两个List的交集,并集方法一

Python中如何控制小数点精度与对齐方式

《Python中如何控制小数点精度与对齐方式》在Python编程中,数据输出格式化是一个常见的需求,尤其是在涉及到小数点精度和对齐方式时,下面小编就来为大家介绍一下如何在Python中实现这些功能吧... 目录一、控制小数点精度1. 使用 round() 函数2. 使用字符串格式化二、控制对齐方式1. 使用