vue3组件通信方式应用场景分析

*父子组件通信

1.父向子传(defineProps)

Vue3 中父组件同样是通过属性传递数据,但子组件接受数据的方式和 Vue2 不同。在

<!-- 父组件 -->
<script setup>
import ChildView from './ChildView.vue'
</script>

<template>
  <ChildView some-prop="parent message" />
</template>


<!-- 子组件 -->
<script setup>
const props = defineProps({
    
    
  someProp: {
    
    
    type: String,
    required: true
  }
})
console.log(props.someProp) // parent message
</script>

<template>
  <!-- 使用 someProp 或 props.someProp -->
  <div>{
    
    {
    
     someProp }}</div>
  <div>{
    
    {
    
     props.someProp }}</div>
</template>

注意:defineProps 、defineEmits 、 defineExpose 和 withDefaults 这四个宏函数只能在

2.子向父传(defineEmits)

Vue2 中子组件数据传递到父组件,通常是使用 $emit 触发一个自定义事件来进行传递。但 $emit 无法在

<!-- 子组件 -->
<script setup>
const emit = defineEmits(['someEvent'])
function onClick() {
    
    
  emit('someEvent', 'child message')
}
</script>

<template>
  <button @click="onClick">点击</button>
</template>


<!-- 父组件 -->
<script setup>
import ChildView from './ChildView.vue'

function someEvent(value) {
    
    
  console.log(value) // child message
}
</script>

<template>
  <ChildView @some-event="someEvent" />
</template>

3.父组件使用子组件数据(defineExpose)

<!-- 子组件 -->
<script setup>
import {
    
     ref } from 'vue'

const msg = ref('hello vue3!')
function change() {
    
    
  msg.value = 'hi vue3!'
  console.log(msg.value)
}
// 属性或方法必须暴露出去,父组件才能使用
defineExpose({
    
     msg, change })
</script>



<!-- 父组件 -->
<script setup>
import ChildView from './ChildView.vue'
import {
    
     ref, onMounted } from 'vue'

const child = ref(null)
onMounted(() => {
    
    
  console.log(child.value.msg) // hello vue3!
  child.value.change() // hi vue3!
})
</script>

<template>
  <ChildView ref="child"></ChildView>
</template>

*隔代/兄弟组件通信

1.依赖注入(provide,inject)

在vue3的中通过provide提供一个值,再由inject向后代注入
详细信息:

  • provide() 接受两个参数:第一个参数是要注入的 key,可以是一个字符串或者一个 symbol,第二个参数是要注入的值。
  • inject() 接受两个参数:第一个参数是注入的 key。Vue 会遍历父组件链,通过匹配 key 来确定所提供的值。如果父组件链上多个组件对同一个 key 提供了值,那么离得更近的组件将会“覆盖”链上更远的组件所提供的值。如果没有能通过 key 匹配到值,inject() 将返回 undefined,除非提供了一个默认值。
  • 第二个参数是可选的,即在没有匹配到 key 时使用的默认值。它也可以是一个工厂函数,用来返回某些创建起来比较复杂的值。如果默认值本身就是一个函数,那么你必须将 false 作为第三个参数传入,表明这个函数就是默认值,而不是一个工厂函数。
  • 与注册生命周期钩子的 API 类似,inject() 必须在组件的 setup() 阶段同步调用。
//爷爷组件
<template>
    <div>
        <h1>GroundFather</h1>
        <Father />
    </div>
</template>
<script setup lang='ts'>
import Father from "./children/Father.vue"
import {
    
     ref, reactive, provide } from 'vue'
const name = 'lufei'
const age = 18
const count = ref(0)
const add = () => {
    
    
    count.value++
}
//提供静态值
provide('name', name)
provide('age', age)
//提供响应式值
provide("count", count)
provide("add",add)
</script>


//父组件
<template>
<div>
    <h2>Father</h2>
    <p>{
    
    {
    
    name}}</p>
    <p>{
    
    {
    
    age}}</p>
    <button @click="add">{
    
    {
    
    count}}</button>
    <Child />
</div>
</template>
<script setup lang='ts'>
import Child from './children/Child.vue'
import {
    
    ref,reactive,inject} from 'vue'
//取默认值
const name = inject('name')
const age = inject('age')
//取响应式值
const count = inject('count')
const add = inject('add')
</script>


//孙子组件
<template>
    <div>
        <h3>Child</h3>
        <p>{
    
    {
    
     name }}</p>
        <p>{
    
    {
    
     age }}</p>
        <button @click="add">{
    
    {
    
     count }}</button>
    </div>
</template>
<script setup lang='ts'>
import {
    
     ref, reactive, inject } from 'vue'
//取默认值
const name = inject('name')
const age = inject('age')
//取响应式值
const count = inject('count')
const add = inject('add')
</script>

效果图:
image.png

2.mitt($bus全局事件总线)

  1. 安装
    npm install --save mitt

  2. 引入

// 因为在vue 3.0 中修改了组建默认使用方式 所以这里要稍作修改
import mitt from 'mitt'

const bus = mitt()
const app = createApp(App)

// 再注册全局事件总线
app.config.globalProperties.$bus = bus

app.use(store).use(router).mount('#app')
  1. 使用
  • 在需要做监听的组件中
//获取当前组建实例 
import {
    
     getCurrentInstance } from 'vue'
    
// 在setup函数中获取实例对象并定义bus
const instance = getCurrentInstance()
const bus = instance.appContext.config.globalProperties.$bus

// 在mounted 函数中声明监听对象
onMounted(()=> {
    
    
    bus.on('bro',(value)=> {
    
    
        console.log('获取其它组建传给我的值' + value)
    })
})
  • 在需要响应传值的对象中
// 获取组建实例对象
import {
    
     getCurrentInstance } from 'vue'
    
// 在setup函数中获取实例对象并定义bus
const instance = getCurrentInstance()
const bus = instance.appContext.config.globalProperties.$bus

// 在自定义方法中
const fn = ()=> {
    
    
    bus.emit('bro','我是传的值')
}

猜你喜欢

转载自blog.csdn.net/qq_52648305/article/details/128957014