Vue父组件子组件的通信方式20种(全网最全总结)

2023-11-04

目录

一、常用

Props

父组件:

子组件:

$emit和$on

父组件:

子组件:

$parent和$children

父组件:

子组件:

$attrs和$listeners

父组件:

子组件:

provide和inject

父组件:

子组件:

二、其他探索

EventBus

父组件:

子组件:

Vuex

store.js:

父组件:

子组件:

$refs属性

父组件:

子组件:

$parent属性

父组件:

子组件:

$root属性

根组件:

子组件:

provide / inject (高级)

祖先组件:

直接子组件:

间接子组件:

provide / inject + Vuex (高级)

根组件:

子组件和孙组件:

自定义事件

父组件:

子组件:

兄弟组件之间的通信

EventBus.js:

组件A:

组件B:

localStorage(浏览器缓存)

组件A:

组件B:

发布订阅(Pub/Sub)模式

消息中心:

组件A:

组件B:

WebSocket (高级)

连接WebSocket服务器:

组件A:

组件B:

路由参数(高级)

父组件:

子组件:

兄弟组件:

Vuex状态管理(高级)

store.js:

组件A:

组件B:

事件总线(高级)

事件总线:

组件A:

组件B:

三、往期优质推荐


一、常用

  • 最近一直在封装各种组件, 提高组员开发效率,
  • 遇到了各种情况下的父子组件, 兄弟组件之间各种传值,
  • 这里做下总结和一些探索, 欢迎补充~

Props

父组件向子组件传递数据,子组件通过props属性接收数据

父组件:

<template>
  <div>
    <child-component :parentData="data"></child-component>
  </div>
</template>

<script>
import ChildComponent from './ChildComponent.vue'

export default {
  components: {
    ChildComponent
  },
  data () {
    return {
      data: '父组件传递的数据'
    }
  }
}
</script>

子组件:

<template>
  <div>
    子组件接收到的数据:{{ parentData }}
  </div>
</template>

<script>
export default {
  props: {
    parentData: String
  }
}
</script>

Vue props默认值类型有哪些

$emit和$on

子组件向父组件传递数据,子组件通过$emit触发事件,父组件通过$on监听事件并接收数据。

父组件:

<template>
  <div>
    <child-component @childEvent="handleChild"></child-component>
  </div>
</template>

<script>
import ChildComponent from './ChildComponent.vue'

export default {
  components: {
    ChildComponent
  },
  methods: {
    handleChild (data) {
      console.log('父组件接收到的数据:' + data)
    }
  }
}
</script>

子组件:

<template>
  <div>
    <button @click="handleClick">点击触发事件</button>
  </div>
</template>

<script>
export default {
  methods: {
    handleClick () {
      this.$emit('childEvent', '子组件传递的数据')
    }
  }
}
</script>

$parent和$children

父组件向子组件传递数据,父组件通过$children获取子组件实例并调用子组件方法传递数据。

父组件:

<template>
  <div>
    <button @click="handleClick">向子组件传递数据</button>
    <child-component ref="child"></child-component>
  </div>
</template>

<script>
import ChildComponent from './ChildComponent.vue'

export default {
  components: {
    ChildComponent
  },
  methods: {
    handleClick () {
      this.$refs.child.handleData('父组件传递的数据')
    }
  }
}
</script>

子组件:

<template>
  <div>
    子组件
  </div>
</template>

<script>
export default {
  methods: {
    handleData (data) {
      console.log('子组件接收到的数据:' + data)
    }
  }
}
</script>

$attrs和$listeners

父组件向子组件传递属性和事件,子组件通过$attrs获取属性,通过$listeners获取事件并绑定在子组件上。

父组件:

<template>
  <div>
    <child-component attr1="属性1" attr2="属性2" @event1="handleEvent"></child-component>
  </div>
</template>

<script>
import ChildComponent from './ChildComponent.vue'

export default {
  components: {
    ChildComponent
  },
  methods: {
    handleEvent (data) {
      console.log('父组件接收到的数据:' + data)
    }
  }
}
</script>

子组件:

<template>
  <div>
    子组件
  </div>
</template>

<script>
export default {
  mounted () {
    this.$emit('event1', '子组件传递的数据')
  }
}
</script>

provide和inject

父组件向子组件传递数据,父组件通过provide提供数据,子组件通过inject注入数据。

父组件:

<template>
  <div>
    <child-component></child-component>
  </div>
</template>

<script>
import ChildComponent from './ChildComponent.vue'

export default {
  components: {
    ChildComponent
  },
  provide () {
    return {
      parentData: '父组件提供的数据'
    }
  }
}
</script>

子组件:

<template>
  <div>
    子组件接收到的数据:{{ childData }}
  </div>
</template>

<script>
export default {
  inject: ['parentData'],
  computed: {
    childData () {
      return this.parentData + ',子组件加工处理后的数据'
    }
  }
}
</script>

二、其他探索

EventBus

父组件和子组件之间通过中央事件总线(EventBus)进行通信。

EventBus.js:

import Vue from 'vue'
export const EventBus = new Vue()

父组件:

<template>
  <div>
    <button @click="handleParent">向子组件传递数据</button>
    <child-component></child-component>
  </div>
</template>

<script>
import ChildComponent from './ChildComponent.vue'
import { EventBus } from './EventBus'

export default {
  components: {
    ChildComponent
  },
  methods: {
    handleParent () {
      EventBus.$emit('parent-event', '父组件传递的数据')
    }
  }
}
</script>

子组件:

<template>
  <div>
    子组件接收到的数据:{{ childData }}
  </div>
</template>

<script>
import { EventBus } from './EventBus'

export default {
  data () {
    return {
      childData: ''
    }
  },
  mounted () {
    EventBus.$on('parent-event', data => {
      this.childData = data
    })
  }
}
</script>

Vuex

父组件和子组件之间通过Vuex进行通信,共享同一状态树。

store.js:

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    data: '共享的数据'
  },
  mutations: {
    setData (state, data) {
      state.data = data
    }
  }
})

父组件:

<template>
  <div>
    <button @click="handleParent">向子组件传递数据</button>
    <child-component></child-component>
  </div>
</template>

<script>
import ChildComponent from './ChildComponent.vue'
import store from './store'

export default {
  components: {
    ChildComponent
  },
  methods: {
    handleParent () {
      store.commit('setData', '父组件传递的数据')
    }
  }
}
</script>

子组件:

<template>
  <div>
    子组件接收到的数据:{{ childData }}
  </div>
</template>

<script>
import { mapState } from 'vuex'

export default {
  computed: {
    ...mapState(['data']),
    childData () {
      return this.data + ',子组件加工处理后的数据'
    }
  }
}
</script>

$refs属性

父组件可以通过$refs获取子组件的实例,进而访问子组件的属性和方法。

父组件:

<template>
  <div>
    <button @click="handleParent">向子组件传递数据</button>
    <child-component ref="child"></child-component>
  </div>
</template>

<script>
import ChildComponent from './ChildComponent.vue'

export default {
  components: {
    ChildComponent
  },
  methods: {
    handleParent () {
      this.$refs.child.childData = '父组件修改的数据'
    }
  }
}
</script>

子组件:

<template>
  <div>
    子组件接收到的数据:{{ childData }}
  </div>
</template>

<script>
export default {
  data () {
    return {
      childData: '子组件原始数据'
    }
  }
}
</script>

$parent属性

子组件可以通过$parent获取父组件的实例,进而访问父组件的属性和方法。

父组件:

<template>
  <div>
    <child-component></child-component>
  </div>
</template>

<script>
import ChildComponent from './ChildComponent.vue'

export default {
  components: {
    ChildComponent
  },
  data () {
    return {
      parentData: '父组件数据'
    }
  },
  methods: {
    handleParent () {
      console.log('父组件的方法')
    }
  }
}
</script>

子组件:

<template>
  <div>
    <button @click="handleChild">调用父组件方法</button>
  </div>
</template>

<script>
export default {
  methods: {
    handleChild () {
      console.log(this.$parent.parentData)
      this.$parent.handleParent()
    }
  }
}
</script>

$root属性

子组件可以通过$root获取根组件的实例,进而访问根组件的属性和方法。

根组件:

<template>
  <div>
    <child-component></child-component>
  </div>
</template>

<script>
import ChildComponent from './ChildComponent.vue'

export default {
  components: {
    ChildComponent
  },
  mounted () {
    console.log('根组件的数据:' + this.rootData)
    this.rootMethod()
  },
  data () {
    return {
      rootData: '根组件的数据'
    }
  },
  methods: {
    rootMethod () {
      console.log('根组件的方法')
    }
  }
}
</script>

子组件:

<template>
  <div>
    子组件
  </div>
</template>

<script>
export default {
  mounted () {
    console.log('根组件的数据:' + this.$root.rootData)
    this.$root.rootMethod()
  }
}
</script>

provide / inject (高级)

provide / inject 可以让祖先组件向所有后代组件注入一个依赖,让这些组件使用相同的依赖注入。

祖先组件:

<template>
  <div>
    <child-component></child-component>
    <grand-child></grand-child>
  </div>
</template>

<script>
import ChildComponent from './ChildComponent.vue'
import GrandChild from './GrandChild.vue'

export default {
  components: {
    ChildComponent,
    GrandChild
  },
  provide: {
    sharedObj: {
      message: '这是祖先组件注入的对象'
    }
  }
}
</script>

直接子组件:

<template>
  <div>
    子组件
  </div>
</template>

<script>
export default {
  inject: ['sharedObj']
}
</script>

间接子组件:

<template>
  <div>
    子组件接收到的数据:{{ childData }}
  </div>
</template>

<script>
export default {
  inject: ['sharedObj'],
  computed: {
    childData () {
      return this.sharedObj.message + ',子组件加工处理后的数据'
    }
  }
}
</script>

provide / inject + Vuex (高级)

使用provide / inject注入Vuex的实例,使所有组件使用相同的Vuex实例。

store.js:

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    data: '共享的数据'
  },
  mutations: {
    setData (state, data) {
      state.data = data
    }
  }
})

根组件:

<template>
  <div>
    <child-component></child-component>
  </div>
</template>

<script>
import ChildComponent from './ChildComponent.vue'
import store from './store'

export default {
  components: {
    ChildComponent
  },
  provide () {
    return {
      store
    }
  }
}
</script>

子组件和孙组件:

<template>
  <div>
    组件接收到的数据:{{ componentData }}
  </div>
</template>

<script>
export default {
  inject: {
    store: {
      default: null
    }
  },
  computed: {
    componentData () {
      return this.store.state.data + ',组件加工处理后的数据'
    }
  }
}
</script>

自定义事件

使用vm.$on(eventName, callback)事件监听,使用vm.$emit(eventName, ...args)触发事件。

父组件:

<template>
  <div>
    <child-component @custom-event="handleCustomEvent"></child-component>
  </div>
</template>

<script>
import ChildComponent from './ChildComponent.vue'

export default {
  components: {
    ChildComponent
  },
  methods: {
    handleCustomEvent (data) {
      console.log('父组件接收到的数据:' + data)
    }
  }
}
</script>

子组件:

<template>
  <div>
    <button @click="handleClick">点击触发事件</button>
  </div>
</template>

<script>
export default {
  methods: {
    handleClick () {
      this.$emit('custom-event', '子组件传递的数据')
    }
  }
}
</script>

兄弟组件之间的通信

使用一个空的Vue实例作为事件总线,一边向事件总线发出事件,另一边监听事件。

EventBus.js:

import Vue from 'vue'
export const EventBus = new Vue()

组件A:

<template>
  <div>
    <button @click="handleClick">向组件B传递数据</button>
  </div>
</template>

<script>
import { EventBus } from './EventBus'

export default {
  methods: {
    handleClick () {
      EventBus.$emit('event', '组件A传递的数据')
    }
  }
}
</script>

组件B:

<template>
  <div>
    组件B接收到的数据:{{ data }}
  </div>
</template>

<script>
import { EventBus } from './EventBus'

export default {
  data () {
    return {
      data: ''
    }
  },
  mounted () {
    EventBus.$on('event', data => {
      this.data = data
    })
  }
}
</script>

localStorage(浏览器缓存)

使用浏览器缓存来存储数据,在需要通信的组件中存储并监听缓存中的数据。

组件A:

<template>
  <div>
    <button @click="handleClick">向组件B传递数据</button>
  </div>
</template>

<script>
export default {
  methods: {
    handleClick () {
      localStorage.setItem('data', '组件A传递的数据')
    }
  }
}
</script>

组件B:

<template>
  <div>
    组件B接收到的数据:{{ data }}
  </div>
</template>

<script>
export default {
  data () {
    return {
      data: ''
    }
  },
  mounted () {
    window.addEventListener('storage', this.handleStorageUpdate)
    this.updateData()
  },
  beforeDestroy () {
    window.removeEventListener('storage', this.handleStorageUpdate)
  },
  methods: {
    handleStorageUpdate (event) {
      if (event.key === 'data') {
        this.updateData()
      }
    },
    updateData () {
      this.data = localStorage.getItem('data') || ''
    }
  }
}
</script>

发布订阅(Pub/Sub)模式

使用一个消息中心,订阅者向消息中心订阅消息,发布者向消息中心发布消息,消息中心将消息通知给所有订阅者。

消息中心:

// PubSub.js
export const PubSub = {
  events: {},
  subscribe (event, callback) {
    if (!this.events[event]) {
      this.events[event] = []
    }
    this.events[event].push(callback)
  },
  publish (event, data) {
    if (!this.events[event]) {
      this.events[event] = []
    }
    this.events[event].forEach(callback => callback(data))
  }
}

组件A:

<template>
  <div>
    <button @click="handleClick">向组件B传递数据</button>
  </div>
</template>

<script>
import { PubSub } from './PubSub'

export default {
  methods: {
    handleClick () {
      PubSub.publish('event', '组件A传递的数据')
    }
  }
}
</script>

组件B:

<template>
  <div>
    组件B接收到的数据:{{ data }}
  </div>
</template>

<script>
import { PubSub } from './PubSub'

export default {
  data () {
    return {
      data: ''
    }
  },
  mounted () {
    PubSub.subscribe('event', data => {
      this.data = data
    })
  }
}
</script>

WebSocket (高级)

使用WebSocket协议实现实时通信,将所有组件连接到同一个WebSocket服务器,通过推送消息实现通信。

连接WebSocket服务器:

const ws = new WebSocket('ws://localhost:3000')

ws.onopen = function () {
  console.log('WebSocket已连接')
}

ws.onclose = function () {
  console.log('WebSocket已关闭')
}

ws.onerror = function () {
  console.log('WebSocket出错')
}

组件A:

<template>
  <div>
    <button @click="handleClick">向组件B传递数据</button>
  </div>
</template>

<script>
const ws = new WebSocket('ws://localhost:3000')

export default {
  methods: {
    handleClick () {
      ws.send('组件A传递的数据')
    }
  }
}
</script>

组件B:

<template>
  <div>
    组件B接收到的数据:{{ data }}
  </div>
</template>

<script>
const ws = new WebSocket('ws://localhost:3000')

export default {
  data () {
    return {
      data: ''
    }
  },
  mounted () {
    ws.onmessage = event => {
      this.data = event.data
    }
  }
}
</script>

路由参数(高级)

使用路由参数来传递数据,通常适用于父子组件之间或兄弟组件之间的通信。

父组件:

<template>
  <div>
    点击以下链接可以传递数据:<br>
    <router-link :to="{ name: 'child', params: { data: '父组件传递的数据' } }">传递数据到子组件</router-link>
  </div>
</template>

子组件:

<template>
  <div>
    子组件接收到的数据:{{ $route.params.data }}
  </div>
</template>

<script>
export default {
  mounted () {
    console.log('子组件接收到的数据:' + this.$route.params.data)
  }
}
</script>

兄弟组件:

<template>
  <div>
    兄弟组件接收到的数据:{{ $route.params.data }}
  </div>
</template>

<script>
export default {
  mounted () {
    console.log('兄弟组件接收到的数据:' + this.$route.params.data)
  }
}
</script>

Vuex状态管理(高级)

使用Vuex管理公共状态,组件通过Vuex进行通信。

store.js:

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    data: '共享的数据'
  },
  mutations: {
    setData (state, data) {
      state.data = data
    }
  }
})

组件A:

<template>
  <div>
    <button @click="handleClick">向组件B传递数据</button>
  </div>
</template>

<script>
import store from './store'

export default {
  methods: {
    handleClick () {
      store.commit('setData', '组件A传递的数据')
    }
  }
}
</script>

组件B:

<template>
  <div>
    组件B接收到的数据:{{ data }}
  </div>
</template>

<script>
import { mapState } from 'vuex'

export default {
  computed: {
    ...mapState(['data'])
  },
  mounted () {
    console.log('组件B接收到的数据:' + this.data)
  }
}
</script>

事件总线(高级)

使用一个空的Vue实例作为事件总线,组件A通过事件总线向组件B传递数据。

事件总线:

// EventBus.js
import Vue from 'vue'
export const EventBus = new Vue()

组件A:

<template>
  <div>
    <button @click="handleClick">向组件B传递数据</button>
  </div>
</template>

<script>
import { EventBus } from './EventBus'

export default {
  methods: {
    handleClick () {
      EventBus.$emit('event', '组件A传递的数据')
    }
  }
}
</script>

组件B:

<template>
  <div>
    组件B接收到的数据:{{ data }}
  </div>
</template>

<script>
import { EventBus } from './EventBus'

export default {
  data () {
    return {
      data: ''
    }
  },
  mounted () {
    EventBus.$on('event', data => {
      this.data = data
    })
  }
}
</script>

三、往期优质推荐

VSCode 最全实用插件(VIP典藏版)
Vue超详细整理(VIP典藏版)
Vue中created,mounted,updated详解
一文快速上手Echarts(持续更新)
Vue中el-table数据项扩展各种类型总结(持续更新)

有用请点赞,养成良好习惯!

疑问、交流、鼓励请留言!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Vue父组件子组件的通信方式20种(全网最全总结) 的相关文章

随机推荐

  • PhotoShop 基础教程-000

    文章目录 前言 总目录 前言 主要讲解photoshop基础知识 所有课程来源B站 PS教程 总目录 第1节 PhotoShop基础课程 版本发展 第2节 PhotoShop基础课程 基础操作 第3节 PhotoShop基础课程 PS界面认
  • Open3D 查看点的坐标

    一 手动选点 函数pick points pcd 创造了一个VisualizerWithEditing实例去模仿draw geometries 创造可视化窗口 添加几何图形 可视化几何图形和结束 VisualizerWithEditing提
  • dnf服务器维护公告,11月18日早4点-12点服务器例行维护公告

    尊敬的DNF用户 为保证服务器的稳定运行 提高游戏品质 我们将于2008年11月18日 周二 凌晨04 00 12 00对所有服务器停机 进行例行维护工作 根据维护工作的进度 停机结束时间有可能提前或者延后 由于福建1区 广东2区 广东3区
  • Apache Beam -- 简介

    概述 在大数据的浪潮之下 技术的更新迭代十分频繁 受技术开源的影响 大数据开发者提供了十分丰富的工具 但也因为如此 增加了开发者选择合适工具的难度 在大数据处理一些问题的时候 往往使用的技术是多样化的 这完全取决于业务需求 比如进行批处理的
  • IT专业技术人员学习网站整理

    1 高端数据资料库 http www chiefdatum com 站点介绍 包含产品数据 学习资料 技术资料 热门图书 眼镜设计 考研 医疗器械等资料为一体的综合性网站 提供专业性下载 2 CSDN NET http www csdn n
  • SpringMVC入门案例

    SpringMVC 概述 SpringMVC是一种基于Java实现MVC模型的轻量级Web框架 三层架构 表现层 负责数据展示 业务层 负责业务处理 数据层 负责数据操作 MVC Model View Controller 一种用于设计创建
  • Java本地缓存CaffeineCache集成

    首先导入需要的依赖
  • 递归展示用户端商品分类列表的层级关系

    递归展示用户端商品分类列表的层级关系 自定义列表实体类 service层 递归调用 自定义列表实体类 添加属性 private List
  • Khan公开课 - 统计学学习笔记:(三)随机变量、概率密度、二项分布、期望值

    随机变量 Random Variable 随机变量和一般数据上的变量不一样 通常用大写字母表示 如X Y Z 不是个参数而是function 即函数 例如 下面表示明天是否下雨的随机变量X 如下 又例如X 每小时经过路口的车辆 随机变量是个
  • MicroPython串口数据转换技巧

    技巧一 还原从串口接收的HEX字符串 首先上官方文档 确认接收数据类型为bytes 串口读来的bytes类型HEX数据转换成HEX类型字符串转换函数 ByteToHex的转换 返回数据16进制字符串 def ByteToHex bins r
  • 使用Nacos实现分布式配置管理和服务发现

    文章目录 一 前言 二 Nacos 1 1什么是Nacos 1 1 1 服务发现和注册 1 1 1 1 服务注册 1 1 1 2 服务发现 1 2 Nacos的使用 1 2 1 配置管理 1 2 2 服务发现 三 结论 一 前言 在现代分布
  • 相关滤波的视觉目标跟踪算法学习

    相关滤波的视觉目标跟踪算法学习内容 1 视觉目标跟踪的难点 训练数据有限 通用目标跟踪任务中 目标先验知识缺乏 仅有目标初始位置信息 目标不确定性 跟踪过程中 随着目标尺寸 形状以及姿态等变化 其外观模 型存在明显差异 多目标跟踪任务中 当
  • 1.2 DICOM成像协议剖析

    以下链接是本系列文章 不足之处 可在评论区讨论 系列文章 1 1 DICOM协议简介及应用 1 2 DICOM成像协议剖析 1 3 DICOM成像协议实现思路 1 4 DICOM图像CT值计算 1 5 DICOM图像CT值转RGB 1 6
  • linux+性能排查,Linux系统性能排查基础

    此文已由作者李晶授权网易云社区发布 欢迎访问 上一期运维季刊中 我们重点从CPU方面分析了Linux系统性能瓶颈 除了CPU之外 内存 IO和网络也是常见的造成系统出现问题的根源 本篇我们继续介绍如何从这三个子系统来排查Linux整个系统的
  • Redis配置数据持久化---APPEND ONLY MODE

    Redis可以实现数据的持久化存储 即将数据保存到磁盘上 Redis的持久化存储提供两种方式 RDB与AOF RDB是默认配置 AOF需要手动开启 现在Redis的配置中默认是关闭AOF模式的 如果要开启AOF模式 修改Redis的配置文件
  • [5机器学习]计算机视觉的世界-卷积神经网络(CNNs)

    我们知道 数据不仅包含文字 数字 还包含图片 视频等 如何更好地查看 识别和解释图像和视频的内容 就像人类视觉一样 一直是目前人工智能的主要研究方向 机器学习无疑是现代数据科学的核心 在经历了几十年回归 分类 决策树 异常检测的沉淀后 数据
  • 期货投资者教育系列丛书 铝

    铝是一种轻金属 其化合物在自然界中分布极广 地壳中铝的资源约为400 500 亿吨 仅次于氧和硅 具第三位 在金属品种中 仅次于钢铁 为第二大类金属 铝具有特殊的化学 物理特性 不仅重量轻 质地坚 而且具有良好的延展性 导电性 导热性 耐热
  • 2022春招前端最新面试题分享(航天宏图)

    航天宏图面经 公司及岗位信息 公司 航天宏图 岗位 前端校招 地点 北京 薪资 10k 15k 面试结果 二面必须让线下面试 去不了 一面 2022 04 21 自我介绍 为什么没有在实习公司转正 实习对于你最大的收获 WebSocket在
  • qt connect 无效_QT 信号槽connect写法

    先看下示例 QPushButton btn new QPushButton 方式一 老式写法 connect btn SIGNAL clicked this SLOT close 方式二 Qt5后新写法 connect btn QPushB
  • Vue父组件子组件的通信方式20种(全网最全总结)

    目录 一 常用 Props 父组件 子组件 emit和 on 父组件 子组件 parent和 children 父组件 子组件 attrs和 listeners 父组件 子组件 provide和inject 父组件 子组件 二 其他探索 E