1、组件通信

父子通信

1.父组件 → 子组件:Props

子组件接收

<script setup> // 声明接收参数 
    const props = defineProps({
        msg: String,
        list: Array,
        num: {     
            type: Number, 
            default: 0 // 默认值   } }) 
</script>  
<template>   
    <div>{{ props.msg }}</div> 
</template>

父组件传值

<Child msg="父传子文字" :list="[1,2,3]" />
2.子组件 → 父组件:defineEmits

子组件触发事件

<script setup>
// 定义要派发的事件
const emit = defineEmits(['sendData'])
​
// 触发事件并传参
const send = () => {
  emit('sendData', '我是子组件的数据', 123)
}
</script>
​
<template>
  <button @click="send">向父传值</button>
</template>

当用户点击页面中的按钮会触发send事件,然后触发emit会发出一个sendData事件,

sendData触发之后被父组件监听到会触发父组件中的handleData函数进行控制台打印

父组件监听

<Child @sendData="handleData" />
​
<script setup>
const handleData = (val, num) => {
  console.log(val, num)
}
</script>

跨层级通信

不用一层层传 props,顶层提供,后代任意层级注入

祖先组件提供数据

<script setup>
import { provide, ref } from 'vue'
​
const name = ref('全局共享名字')
// 提供 key 和 值
provide('globalName', name)
</script>

任意后代组件注入使用

<script setup>
import { inject } from 'vue'
// 注入对应key
const globalName = inject('globalName')
</script>
​
<template>
  <div>{{ globalName }}</div>
</template

优点:跨级极简;缺点:数据追踪不清晰,适合主题、配置类全局数据。

模板引用

当父组件想要调用子组件里的方法 / 变量。使用defineExpose进行方法暴露和使用

子组件暴露

<script setup>
const fn = () => {
  alert('子组件方法')
}
// 暴露出去
defineExpose({ fn })
</script>

父组件调用

<template>
  <Child ref="childRef" />
</template>
​
<script setup>
import { ref, onMounted } from 'vue'
const childRef = ref(null)
​
onMounted(() => {
  childRef.value.fn() // 调用子组件方法
})
</script>

易错点------父子通信vs模板引用

1、defineExpose和父子通信中的emit的区别

  • emit:子 → 父 主动发消息(子喊父)

    场景

    • 子组件按钮被点击了

    • 子组件表单提交了

    • 子组件数据变了

    • 子组件要把数据传给父

      特点

      子主动触发

      父被动监听

      只能传数据,不能调用方法

  • defineExpose:父 → 子 主动调用(父喊子)

    场景

    1、父要让子组件执行某个动作

    • 打开弹窗

    • 重置表单

    • 刷新列表

    • 执行动画

    2、父直接调用子的方法

    特点

    父主动调用

    子被动执行

    可以调用方法,也可以拿数据

更多推荐