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

相关文章

python logging模块详解及其日志定时清理方式

《pythonlogging模块详解及其日志定时清理方式》:本文主要介绍pythonlogging模块详解及其日志定时清理方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地... 目录python logging模块及日志定时清理1.创建logger对象2.logging.basicCo

C#TextBox设置提示文本方式(SetHintText)

《C#TextBox设置提示文本方式(SetHintText)》:本文主要介绍C#TextBox设置提示文本方式(SetHintText),具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑... 目录C#TextBox设置提示文本效果展示核心代码总结C#TextBox设置提示文本效果展示核心代

SpringValidation数据校验之约束注解与分组校验方式

《SpringValidation数据校验之约束注解与分组校验方式》本文将深入探讨SpringValidation的核心功能,帮助开发者掌握约束注解的使用技巧和分组校验的高级应用,从而构建更加健壮和可... 目录引言一、Spring Validation基础架构1.1 jsR-380标准与Spring整合1

Vuex Actions多参数传递的解决方案

《VuexActions多参数传递的解决方案》在Vuex中,actions的设计默认只支持单个参数传递,这有时会限制我们的使用场景,下面我将详细介绍几种处理多参数传递的解决方案,从基础到高级,... 目录一、对象封装法(推荐)二、参数解构法三、柯里化函数法四、Payload 工厂函数五、TypeScript

Android实现打开本地pdf文件的两种方式

《Android实现打开本地pdf文件的两种方式》在现代应用中,PDF格式因其跨平台、稳定性好、展示内容一致等特点,在Android平台上,如何高效地打开本地PDF文件,不仅关系到用户体验,也直接影响... 目录一、项目概述二、相关知识2.1 PDF文件基本概述2.2 android 文件访问与存储权限2.

SpringQuartz定时任务核心组件JobDetail与Trigger配置

《SpringQuartz定时任务核心组件JobDetail与Trigger配置》Spring框架与Quartz调度器的集成提供了强大而灵活的定时任务解决方案,本文主要介绍了SpringQuartz定... 目录引言一、Spring Quartz基础架构1.1 核心组件概述1.2 Spring集成优势二、J

Java中Date、LocalDate、LocalDateTime、LocalTime、时间戳之间的相互转换代码

《Java中Date、LocalDate、LocalDateTime、LocalTime、时间戳之间的相互转换代码》:本文主要介绍Java中日期时间转换的多种方法,包括将Date转换为LocalD... 目录一、Date转LocalDateTime二、Date转LocalDate三、LocalDateTim

Spring中配置ContextLoaderListener方式

《Spring中配置ContextLoaderListener方式》:本文主要介绍Spring中配置ContextLoaderListener方式,具有很好的参考价值,希望对大家有所帮助,如有错误... 目录Spring中配置ContextLoaderLishttp://www.chinasem.cntene

golang获取当前时间、时间戳和时间字符串及它们之间的相互转换方法

《golang获取当前时间、时间戳和时间字符串及它们之间的相互转换方法》:本文主要介绍golang获取当前时间、时间戳和时间字符串及它们之间的相互转换,本文通过实例代码给大家介绍的非常详细,感兴趣... 目录1、获取当前时间2、获取当前时间戳3、获取当前时间的字符串格式4、它们之间的相互转化上篇文章给大家介

Vue3使用router,params传参为空问题

《Vue3使用router,params传参为空问题》:本文主要介绍Vue3使用router,params传参为空问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐... 目录vue3使用China编程router,params传参为空1.使用query方式传参2.使用 Histo