likes
comments
collection
share

vue3组件通信看一篇就够

作者站长头像
站长
· 阅读数 3

前言

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

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

父子组件通信

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

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

<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数据源中

 <!-- 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发布一个事件,父组件订阅该事件

 <!-- 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的事件就自动触发

 <!-- 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 接收属性和自定义事件,且子组件内部使用接收的自定义事件修改接收到的属性值,然后父组件根据绑定的自定义事件接收到子组件传递过来的新数据,从而实现父子组件数据同步。

 <!-- 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>
<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读取着整个子组件对象来获取值

 <!-- 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的值

<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

<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来提供数据,但是这个子组件 或者孙子组件都可以来接收,但是这种不建议用这个,因为这个值在别的地方改变了,这个全部组件都跟着改变

<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插件(事件总线)

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

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