vue3组件通信看一篇就够

前言

📢最近准备春招啦了,所以整理了一些前端高频大厂面试题,分享给大家,如有问题欢迎留言指正,面试专栏我会长期更新,欢迎大家点赞🤞、收藏📌,关注➕,感谢!

Vue 组件通信是指在 Vue.js 应用程序中,不同的组件之间进行数据传递和交互的过程。Vue 提供了多种方式来实现组件通信,包括父子组件通信、兄弟组件通信和跨级组件通信等。

父子组件通信

  • 父组件通过 props 向子组件传递数据。
  • 子组件通过 $emit 触发事件,将数据发送给父组件。
  • 子父通信 子组件拿到父组件的数据并修改后emit出来,父组件靠v-model实现双向绑定
  • 子父通信 子组件defineExpose暴露出来值,父组件利用ref读取着整个子组件对象来获取值
  • 父子通信 父组件 provied 子组件 inject
  • EventBus mitt插件,也就是事件总线来传值

父组件通过 props 向子组件传递数据。

xml 复制代码
<template>
 <!-- parent -->
 <div class="hd">
   <input type="text" name="" id="" v-model="msg">
   <button @click="add">添加</button>
 </div>
 <!-- child -->
 <Child :message="message"/>
</template>
<script setup>
import { ref } from 'vue';
import Child from './components/Child_1.vue'
const msg = ref('')
const message = ref('')
const add = () => {
message.value = msg.value
}
</script>

通过引入子组件,在子组件标签中通过动态绑定数据源message,在点击事件获取表单输入的值,在加入message数据源中

xml 复制代码
 <!-- child -->
<template>
  <div class="bd">
    <ul>
      <li v-for="item in list">{{item}}</li>
    </ul>
  </div>
</template>
<script setup>
import { ref } from 'vue';
const list = ref(['html', 'css'])
defineProps({
  message: String,
  default: ''
})
</script>

子组件通过difineProps为一个对象,message为String,default这个是设置默认值的,然后可以渲染到子组件当中去

子组件 emit发布一个事件,父组件订阅该事件

xml 复制代码
 <!-- parent -->
<template>
  <Child @add="handle"/>
  <div class="bd">
    <ul>
      <li v-for="item in list">{{item}}</li>
    </ul>
  </div>
</template>
<script setup>
import { ref } from 'vue';
import Child from './components/Child_2.vue'
const list = ref(['html', 'css'])
const handle = (e) => {
  console.log(e);
  list.value.push(e)
}
</script>

自定义事件,通常用来进行 子 -> 父 之间的事件传递,自定义一个add事件,当add事件触发时,handle的事件就自动触发

xml 复制代码
 <!-- child -->
<template>
  <div class="hd">
    <input type="text" name="" id="" v-model="msg">
    <button @click="add">添加</button>
  </div>
</template>
<script setup>
import { ref } from 'vue';
const msg = ref('')
const emits = defineEmits(['add'])  // 创建一个add事件
const add = () => {
  emits('add', msg.value);  // 发布add事件
}
</script>
<style lang="css" scoped>
</style>

子父传值这个是重点const emits = defineEmits('add') 创建一个事件, emits('add', msg.value); 发布add事件

双向绑定

在子组件标签上绑定属性和自定义事件,子组件内部使用 definePropsdefineEmits 接收属性和自定义事件,且子组件内部使用接收的自定义事件修改接收到的属性值,然后父组件根据绑定的自定义事件接收到子组件传递过来的新数据,从而实现父子组件数据同步。

xml 复制代码
 <!-- parent -->
<template>
  <Child v-model:list="list"/>
  <div class="bd">
    <ul>
      <li v-for="item in list">{{item}}</li>
    </ul>
  </div>
</template>
<script setup>
import { ref } from 'vue';
import Child from './components/Child_3.vue'
const list = ref(['html', 'css'])
</script>
xml 复制代码
<template>
  <div class="hd">
    <input type="text" name="" id="" v-model="msg">
    <button @click="add">添加</button>
  </div>
</template>
<script setup>
import { ref } from 'vue';
const msg = ref('')
const props = defineProps({
  list: {
    type: Array,
    default: () => []
  }
})
const emits = defineEmits(['update:list'])
const add = () => {
  // props.list.push(msg.value) // xxxxxx
  const arr = props.list
  arr.push(msg.value)
  emits('update:list', arr)
}
</script>

子组件defineExpose暴露出来值,父组件利用ref读取着整个子组件对象来获取值

xml 复制代码
 <!-- parent -->
<template>
  <Child ref="childRef"/>
  <div class="bd">
    <ul>
      <li v-for="item in childRef?.list">{{item}}</li>
    </ul>
  </div>
</template>
<script setup>
import { ref } from 'vue';
import Child from './components/Child_4.vue'
const childRef = ref(null)
</script>

获取子组件的dom结构 <Child ref="childRef"/> 来获取list的值

xml 复制代码
<template>
 <div class="hd">
   <input type="text" name="" id="" v-model="msg">
   <button @click="add">添加</button>
 </div>
</template>
<script setup>
import { ref } from 'vue';
const msg = ref('')
const list = ref(['html', 'css'])
const add = () => {
 list.value.push(msg.value)
}
defineExpose({ list }) // 愿意暴露出来的变量
</script>

通过defineExpose来暴露出list值,来给父组件来应用

父组件 provied 子组件 inject

xml 复制代码
<template>
 <div class="hd">
   <input type="text" name="" id="" v-model="msg">
   <button @click="add">添加</button>
 </div>
 <Child/>
</template>
<script setup>
import { ref, provide } from 'vue';
import Child from './components/Child_5.vue'
const msg = ref('')
const list = ref(['html', 'css'])
provide('list', list.value)
const add = () => {
 list.value.push(msg.value)
}
</script>
<style lang="css" scoped>
</style>

通过provide来提供数据,但是这个子组件 或者孙子组件都可以来接收,但是这种不建议用这个,因为这个值在别的地方改变了,这个全部组件都跟着改变

xml 复制代码
<template>
  <div class="bd">
    <ul>
      <li v-for="item in list">{{item}}</li>
    </ul>
    <Child52 />
  </div>
</template>
<script setup>
import { ref, inject } from 'vue';
import Child52 from './Child_5.2.vue'
const list = inject('list');
</script>
<style lang="css" scoped>
</style>

父组件用provide来提供list数据,子组件用inject来接受父组件传来的值,孙子组件都可以用inject来接收

EventBus mitt插件(事件总线)

这个方法可以自己可以去查查看。

如觉得本文对你有帮助的话,欢迎点赞❤❤❤,写作不易,持续输出的背后是无数个日夜的积累,您的点赞是持续写作的动力,感谢支持

相关推荐
LEE3 小时前
前端转型全栈 00:AI 时代该学哪些,不该学哪些
前端·后端
晚安日记wanna4 小时前
SSR 为什么不适合登录态从水合冲突到缓存串号
前端·react.js·面试
晚安日记wanna4 小时前
压测 TPS 卡在 800CPU 只跑四成六步定位法
运维·面试·测试
aixingpan4 小时前
aixingpan.cn API开发文档:api_docs_bichart_natalvssolararc2接口指南
前端·php
无限压榨切图仔4 小时前
一个优惠券需求改了三端,我才明白全栈不是多学一门语言
前端·后端
晚安日记wanna4 小时前
批量请求失败只弹一个 Toast面试官想听五层
前端·面试·架构
晚安日记wanna4 小时前
TS const 类型参数一道面试题的四层追问
前端·面试·typescript
晚安日记wanna4 小时前
大表 DDL 面试翻车现场Online DDL 为什么还会锁死业务
数据库·面试·架构
用户921080262864 小时前
前端 Vue 专栏 09:Vue Router 与前端路由
前端
晚安日记wanna4 小时前
MySQL 主从延迟别只答并行复制
数据库·面试·架构