vue3父子组件通信

139 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第5天,点击查看活动详情

定义:

组件都是一个相互独立的个体,但是在具体项目中我们需要组件相互之建立联系,这个联系我们就称之为组件通信

分类:

根据组件的分类及嵌套模式,组件通信也可以分为父子组件通信(包括嵌套层级很深的后代组件通信),兄弟组件通信

方式:

父子组件通信:

defineProps(父传子)和defineEmits(子传父)

父组件通过v-bind传值,子组件通过defineProps接受传过来的值

父组件:

<template>
    <div>
        <Child :total="total"></Child>
    </div>
</template>

子组件通过defineProps接受值:

defineProps({
    total:{
        default:"",
        type:string
    }
})

子组件给父组件传值时通过defineEmits触发一个事件

子组件:

<template>
    <div>
        <div @click="clickBtn">触发事件传值给父组件</div>
    </div>
</template>
 
<script setup lang="ts">
import { reactive } from 'vue'
const arr = reactive<number[]>([1, 2, 3])
 
const emit = defineEmits(['on-click'])

const clickBtn = () => {
    emit('on-click', arr)
}
</script>

子组件通过click 事件,用defineEmits 注册了一个自定义事件,当子组件被点击时会触发click,通过 emit 去调用注册的事件,然后传递参数

父组件接受子组件的值的事件,通过defineExpose暴露拿到

<template>
    <div>
        <Child @on-click="getArr"></Child>
    </div>
</template>
 
<script setup lang="ts">
import { reactive } from 'vue';
 
const data = reactive<number[]>([1, 2, 3])
    
defineExpose({
    data
})
const getArr = (arr: number[]) => {
    console.log(arr,'父组件接受子组件的值');
}
</script>

provide/inject  组件通信

祖先后代之间(嵌套层级更高的父子组件组件)组件通信可以通过provide 提供数据和函数,在后代组件中通过inject接收祖先传递的数据和函数

在组合式 API 中使用 provide/inject,vue3中这两个属性只能在 setup 期间调用,使用前,必须从 vue 中导入 provide/inject 方法

provide 函数接收两个参数,为:provide( name,value )

name:定义提供 property 的 name value :property 的值

import { provide } from "vue" 
export default { 
setup(){ provide('arr',"数据") 
} 
}

inject 函数也有有两个参数:inject(name,default)

name:接收 provide 提供的属性名 default:设置默认值,是可选参数,可以不写

import { inject } from "vue"
export default {
setup(){ inject('info',"设置默认值") 
} 
}

具体使用: 父组件:

<template>
  <div> 
    <Child></Child>
  </div>
</template>
 
<script>
 
import Child from "./Child"
import { provide,readonly,ref } from "vue"
export default {
  setup(){
    let total = ref("所有数值")
    provide('total',totaltotal)
    return{
      total
    }
  }
  components:{
    Child
  }
}
</script>

子组件:

<template>
 {{total}}
</template>
 
<script>
 
import { inject } from "vue"
export default {
  setup(){
    const total = inject('info')
    total.value = "总数又多一条"
    return{
      total
    }
  }
}
</script>