总结vue中常用的组件间通信的方法

这也是面试经常问到的一道题,正好近期刷到这道题, 然后就写写小demo,顺便将父子组件通信,兄弟组件通信, 跨组件通信, 总结复习一下.

1. props

1.1 props 的基本介绍:

  1. 定义 props :在子组件中,你需要定义一个 props 选项,列出你想要从父组件接收的所有属性。每个属性可以是一个字符串数组,或者是一个带有更多选项的对象,如类型 type、默认值 default 和是否必须 required
  2. 传递 props :在父组件的模板中,你可以通过动态属性 v-bind 或简写为 : 来传递数据给子组件。
  3. 类型验证 :你可以为 props 指定期望的类型,例如 StringNumberArrayObject 等。如果传入的数据类型不匹配,Vue 将在浏览器控制台发出警告。
  4. 默认值 :可以为 props 提供一个默认值,如果父组件没有传递该属性,子组件将使用默认值。
  5. 必需性 :通过设置 requiredtrue,你可以指定一个 prop 是必需的。如果父组件没有传递这个必需的 prop,Vue 将在浏览器控制台发出警告。

1.2 示例

父组件

fater.vue

js 复制代码
<template>
  <!-- 也可以直接将数据传递给子组件 -->
  <Child :user="user" :hobby="['篮球', '足球']" :iphone="123456789"></Child>
</template>

<script setup>
import { ref } from "vue"
import Child from "./components/child.vue";

// 可以在这里定义好数据, 上面指定
const user = {
    name: '小明',
    age: 18
}

</script>

子组件child.vue

js 复制代码
<template>
    <h2>我是子组件 child.vue</h2>
    <h3>下方是接收来自父组件的数据</h3>
    <div>
        {{ user.name }}
    </div>
    <div>
        {{ user.age }}
    </div>

    <ul>
        <li v-for="item in hobby">{{ item }}</li>
    </ul>
    <div>手机号 {{ iphone }}</div>
</template>

<script setup>
import { ref } from "vue"
defineProps({
    // 对象
    user: {
        type: Object,
        required: true
    },
    // 数组
    hobby: {
        type: Array, // 类型
        default: [], // 默认值
        required: true // 必须,如果父组件不传入, 虽然不会导致报错, 但浏览器会有警告
    },
    // 字符串
    iphone: {
        type: String
    }
});
</script>

页面效果

2. $emit

子组件将数据传递给父组件

2.1 emit 的基本用法:

  1. 注册事件 :在子组件中,你可以使用 defineEmits 函数来声明一个或多个自定义事件。
  2. 触发事件 :在子组件的逻辑中,你可以调用 emit 函数并传递事件名称和一个或多个参数。这些参数将被作为事件的数据传递给父组件。
  3. 监听事件 :父组件可以在模板中通过 v-on 或简写为 @ 来监听子组件触发的事件,并定义一个事件处理函数来接收这些数据。

2.2 代码示例

子组件 child.vue

js 复制代码
<template>
    <div>
        <button @click="handleClick">发送给父组件数据</button>
    </div>
</template>

<script setup>
import {ref} from 'vue'

// 注册一个自定义事件名,向上传递时告诉父组件要触发的事件。
const emit = defineEmits(['changeMsg'])

// 定义好要传递给父组件的数据
const data = ref("这是子组件的数据")

function handleClick() {
    //    注册事件名字 以及传递给父组件的参数
    emit('changeMsg', data.value)
}

</script>

父组件 father.vue

js 复制代码
<template>
  <h1>来自子组件的数据:<span style="color: red;">{{ dataFromChild }}</span></h1>
  <!-- 这里的自定义事件名字 需要和子组件注册的名字保持一致 -->
  <Child @changeMsg="getDataFromChild" />
</template>

<script setup>
import { ref } from 'vue'
import Child from './components/child.vue'

const dataFromChild = ref("默认值")

const getDataFromChild = (data) => {
  console.log(data); // 这里可以拿到子组件传过来的数据
  dataFromChild.value = data // 将子组件拿到的数据 赋值给父组件的变量值
}
</script>

效果:

3. provide 提供 和 inject 注入

3.1 依赖注入基本介绍

一个父组件相对于其所有的后代组件,会作为依赖提供者 。任何后代的组件树,无论层级有多深,都可以注入由父组件提供给整条链路的依赖。 ---> 引自官方

provide() 函数接收两个参数。第一个参数被称为注入名 ,可以是一个字符串或是一个 Symbol。后代组件会用注入名来查找期望注入的值。一个组件可以多次调用 provide(),使用不同的注入名,注入不同的依赖值。

3.2 示例代码

父组件

js 复制代码
<template>
  <div>
    <Child></Child>
    <br>
    <Child1></Child1>
  </div>
</template>

<script setup>
import {ref,provide} from 'vue'
import Child from './components/child.vue';
import Child1 from './components/child1.vue';
// 可以提供多个值
provide('data',{
  msg: ref('hello.this message from parent component'),
  count: ref(0)
})

// 也可以提供单个值
provide("test","hello this is test")

</script>

子组件1

js 复制代码
<template>
    子组件2:这是来自父组件的数据 : <span style="color:red">{{ data.msg }}</span> count : {{ data.count }}
    <br>
    test:{{ test }}

</template>

<script setup>
import { ref, inject } from "vue"
// 父组件 使用inject 接收子组件provide 传递过来的数据
const data = inject('data')
const test = inject('test')

</script>

子组件2

js 复制代码
<template>
    子组件2:这是来自父组件的数据 :  <span style="color:red">{{ data. msg}}</span> count : {{ data.count }}
    <br>
    test:{{ test }}

</template>

<script setup>
import { ref, inject } from "vue"
// 父组件 使用inject 接收子组件provide 传递过来的数据
const data = inject('data')
const test = inject('test')

</script>

解释:

父组件通过将自身的数据使用provide 提供给所有子组件, 子组件可以使用inject方法接收父组件向外提供的值. 注意 provide 和 inject 的注入名保持一致, 这样才可以正常接收到数据

效果图:

4. ref 和 defineExpose

4.1 基本介绍

defineExpose 是一个在 <script setup> 中使用的 API,它允许组件显式地暴露其数据或方法,使得这些数据和方法可以在组件的外部被访问。

4.2 代码示例

子组件

我们通过defineExpose 方法将子组件的变量 和 方法向外暴露

js 复制代码
<template>
</template>

<script setup>
import { ref } from "vue"

const data = ref("我是子组件内部的数据")
const updataData = () => {

    data.value = "更新子组件内部的数据"
}

// 将组件内部的一些函数或数据暴露给父组件
defineExpose({
    data,
    updataData
})

</script>

父组件

通过ref 拿到子组件的实例

js 复制代码
<template>
  <div>
    <Child ref="child" />
    <button @click="updateMsg">更新子组件数据</button>
    这是来自子组件的数据:  <span style="color: red;">{{  mes }}</span>
  </div>
</template>

<script setup>
import { ref,onMounted } from 'vue'
import Child from './components/child.vue'

// 通过ref 获取到子组件的实例
const child = ref(null)

const mes = ref("")
const updateMsg = () => {
    child.value.updataData()
    mes.value = child.value.data
}
onMounted(() => {
  // 确保子组件已经挂载
  if (child.value) {
    console.log(child.value.data); // 访问子组件暴露的 data
    mes.value = child.value.data
  }
})

</script>

子组件的实例

效果:

调用子组件暴露的方法,父组件点击按钮之后, 执行子组件的那个更新数据的方法

相关推荐
庸俗今天不摸鱼21 分钟前
【万字总结】前端全方位性能优化指南(十)——自适应优化系统、遗传算法调参、Service Worker智能降级方案
前端·性能优化·webassembly
黄毛火烧雪下28 分钟前
React Context API 用于在组件树中共享全局状态
前端·javascript·react.js
Apifox39 分钟前
如何在 Apifox 中通过 CLI 运行包含云端数据库连接配置的测试场景
前端·后端·程序员
一张假钞41 分钟前
Firefox默认在新标签页打开收藏栏链接
前端·firefox
高达可以过山车不行42 分钟前
Firefox账号同步书签不一致(火狐浏览器书签同步不一致)
前端·firefox
m0_5937581043 分钟前
firefox 136.0.4版本离线安装MarkDown插件
前端·firefox
掘金一周1 小时前
金石焕新程 >> 瓜分万元现金大奖征文活动即将回归 | 掘金一周 4.3
前端·人工智能·后端
三翼鸟数字化技术团队1 小时前
Vue自定义指令最佳实践教程
前端·vue.js
Jasmin Tin Wei2 小时前
蓝桥杯 web 学海无涯(axios、ecahrts)版本二
前端·蓝桥杯
圈圈编码2 小时前
Spring Task 定时任务
java·前端·spring