Vue3父子组件间传参通信

这篇具有很好参考价值的文章主要介绍了Vue3父子组件间传参通信。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

本文主要是记录Vue3在setup语法糖下的父子组件间传参的四种方式

Vue3+TypeScript

一、父传子 defineProps

父组件传值给子组件主要是由父组件为子组件通过v-bind绑定数值,而后传给子组件;子组件则通过defineProps接收使用。

如下为父组件Father.vue

<template>
  <div class="fa">
    <div style="margin: 10px;">我是父组件</div>
    <Son :fatherMessage="fatherMessage"></Son>
  </div>
</template>

<script setup lang="ts">
import Son from './Son.vue'
import {ref} from "vue";

const fatherMessage = ref<string>("我是父组件传过来的值")

</script>

<style scoped>
.fa{
  border: 3px solid cornflowerblue;
  width: 400px;
  text-align: center;
}
</style>

如下为子组件Son.vue

<template>
  <div style="margin: 10px;border: 2px solid red">
    我是子组件
    <div style="margin: 5px;border: 2px solid gold">
      父组件传值接收区:{{fatherMessage}}
    </div>
  </div>
</template>

<script setup lang="ts">
interface Props {
  fatherMessage?: string,
}
defineProps<Props>()

</script>

父组件Father.vue中在调用Son.vue这个子组件时,使用v-bind绑定参数fatherMessage,并传给Son.vue

子组件Son.vue使用defineProps接收fatherMessage这个参数,而后就可以正常使用该参数。

二、子传父 defineEmits

子组件传值给父组件主要是子组件通过defineEmits注册一个自定义事件,而后触发emit去调用该自定义事件,并传递参数给父组件。

在父组件中调用子组件时,通过v-on绑定一个函数,通过该函数获取传过来的值。

如下为子组件Son.vue

<template>
  <div style="margin: 10px;border: 2px solid red">
    我是子组件
    <button @click="transValue" style="margin: 5px">传值给父组件</button>
  </div>
</template>

<script setup lang="ts">
import {ref} from "vue";

// 定义所要传给父组件的值
const value = ref<String>("我是子组件传给父组件的值")

// 使用defineEmits注册一个自定义事件
const emit = defineEmits(["getValue"])

// 点击事件触发emit,去调用我们注册的自定义事件getValue,并传递value参数至父组件
const transValue = () => {
  emit("getValue", value.value)
}

</script>

如下为父组件Father.vue

<template>
  <div class="fa">
    <div style="margin: 10px;">我是父组件</div>
    父组件接收子组件传的值:{{sonMessage}}
    <Son @getValue="getSonValue"></Son>
  </div>
</template>

<script setup lang="ts">
import Son from './Son.vue'
import {ref} from "vue";

const sonMessage = ref<string>("")
const getSonValue = (value: string) => {
  sonMessage.value = value
}
</script>

<style scoped>
.fa{
  border: 3px solid cornflowerblue;
  width: 400px;
  text-align: center;
}
</style>

父组件Father.vue中在调用Son.vue这个子组件时,当子组件Son.vue需要传参给父组件Father.vue时,使用defineEmits注册一个事件getValue,而后设置点击事件transValue去触发emit,去调用我们注册的自定义事件getValue,并传递value参数至父组件。

父组件Father.vue在获取子组件Son.vue传过来的值时,通过在子组件上使用v-on设置响应函数getValue(该函数与子组件中的注册自定义事件getValue名称需一致),并绑定一个函数getSonValue来获取传过来的值。

三、子组件暴露属性给父组件 defineExpose

当父组件想直接调用父组件的属性或者方法时,子组件可以使用defineExpose暴露自身的属性或者方法,父组件中使用ref调用子组件暴露的属性或方法。
如下为子组件Son.vue

<template>
  <div style="margin: 10px;border: 2px solid red">
    我是子组件

  </div>
</template>

<script setup lang="ts">
import {ref, defineExpose} from "vue";

// 暴露给父组件的值
const toFatherValue = ref<string>("我是要暴露给父组件的值")

// 暴露给父组件的方法
const toFatherMethod = () => {
  console.log("我是要暴露给父组件的方法")
}
// 暴露方法和属性给父组件
defineExpose({toFatherMethod, toFatherValue})

</script>

如下为父组件Father.vue

<template>
  <div class="fa">
    <div style="margin: 10px;">我是父组件</div>
    <button @click="getSonMethod">获取子组件的方法</button>
    <Son ref="sonMethodRef"></Son>
  </div>
</template>

<script setup lang="ts">
import Son from './Son.vue'
import {ref} from "vue";

const sonMethodRef = ref()

const getSonMethod = () => {
  sonMethodRef.value.toFatherMethod()
  console.log(sonMethodRef.value.toFatherValue)
}

</script>

<style scoped>
.fa{
  border: 3px solid cornflowerblue;
  width: 400px;
  text-align: center;
}
</style>

在子组件中定义属性toFatherValue和方法toFatherMethod,而后通过defineExpose暴露出来。
父组件调用时,为子组件绑定一个ref,并定义一个ref变量sonMethodRef,通过调用sonMethodRef,来获取子组件暴露出来的属性和方法。

四、依赖注入Provide / Inject

从上面的介绍里我们可以了解到父子组件之间的通信,但是却存在这样的情况:有一些多层级嵌套的组件,形成了一颗巨大的组件树,而某个深层的子组件需要一个较远的祖先组件中的部分数据。在这种情况下,如果仅使用 props 则必须将其沿着组件链逐级传递下去,这会非常麻烦:
vue3父子组件传参,TypeScript,Vue3,javascript,vue.js,前端

虽然这里的 Footer 组件可能根本不关心这些 props,但为了使 DeepChild 能访问到它们,仍然需要定义并向下传递。如果组件链路非常长,可能会影响到更多这条路上的组件。这一问题被称为“prop 逐级透传”,显然是我们希望尽量避免的情况。
provideinject 可以帮助我们解决这一问题。 一个父组件相对于其所有的后代组件,会作为依赖提供者。任何后代的组件树,无论层级有多深,都可以注入由父组件提供给整条链路的依赖。
vue3父子组件传参,TypeScript,Vue3,javascript,vue.js,前端
如下为父组件Root.vue

<template>
  <div>
    我是root组件
    <Footer></Footer>
  </div>
</template>

<script setup lang="ts">
import { provide, ref } from 'vue'
import Footer from './Footer.vue'

const toChildValue= ref<string>("我是给所有子组件的值")

// 将toChildValue注入到所有子组件中
provide(/* 注入名 */ 'toChildValue', /* 值 */ toChildValue)

</script>

如下为子组件Footer.vue

<template>
  <div>
    我是footer组件
    <div>
      接收父组件的值:{{getFatherValue}}
    </div>
    <DeepChild></DeepChild>
  </div>
</template>

<script setup lang="ts">
import DeepChild from "./DeepChild.vue"
import {ref,inject,Ref} from "vue";

// 获取父组件提供的值
// 如果没有祖先组件提供 "toChildValue"
// ref("") 会是 "这是默认值"
const getFatherValue = inject<Ref<string>>(/* 注入名 */"toChildValue",/* 默认值 */ ref(""))

</script>

如下为孙子组件DeepChild.vue

<template>
  <div>
    我是deepChild组件
    <div>
      接收爷爷组件的值:{{getGrandFatherValue}}
    </div>
  </div>
</template>

<script setup lang="ts">
import {inject, ref, Ref} from "vue";

// 获取爷爷组件提供的值
// 如果没有爷爷组件提供 "toChildValue"
// value 会是 ""
const getGrandFatherValue = inject<Ref<string>>(/* 注入名 */"toChildValue",/* 默认值 */ ref(""))
</script>

当最顶层的组件Root.vue传值给所有子组件时,使用provide进行注入

provide(/* 注入名 */ 'toChildValue', /* 值 */ toChildValue)

而后无论哪个子组件想要获取toChildValue的值,只需使用inject即可

inject<Ref<string>>(/* 注入名 */"toChildValue",/* 默认值 */ ref(""))

当提供 / 注入响应式的数据时,如果想改变数据时,建议尽可能将任何对响应式状态的变更都保持在供给方组件中,即根组件Root.vue。这样可以确保所提供状态的声明和变更操作都内聚在同一个组件内,使其更容易维护。

有的时候,我们可能需要在注入方组件中更改数据。在这种情况下,我们推荐在供给方组件内声明并提供一个更改数据的方法函数:
如下为父组件Root.vue

<template>
  <div>
    我是root组件
    <Footer></Footer>
  </div>
</template>

<script setup lang="ts">
import {InjectionKey, provide, Ref, ref} from 'vue'
import Footer from './Footer.vue'

const toChildValue= ref<string>("我是给所有子组件的值")
/**
 * 修改父组件值的方法
 */
const changeValue = () => {
  toChildValue.value = "我是父组件修改的值"
}
// 定义一个注入key的类型(建议将注入 key 的类型放在一个单独的文件中,这样它就可以被多个组件导入)
interface ProvideType {
  toChildValue: Ref<string>;
  changeValue: () => void;
}
// 为注入值标记类型
const toValue = Symbol() as InjectionKey<ProvideType>
// 将toChildValue和changeValue注入到所有子组件中
provide(/* 注入名 */ 'toValue', /* 值 */{
  toChildValue,
  changeValue
})
</script>

provideinject 通常会在不同的组件中运行。要正确地为注入的值标记类型,Vue 提供了一个 InjectionKey 接口,它是一个继承自 Symbol 的泛型类型,可以用来在提供者和消费者之间同步注入值的类型。
建议将注入 key 的类型放在一个单独的文件中,这样它就可以被多个组件导入。

// 定义一个注入key的类型
//(建议将注入 key 的类型放在一个单独的文件中,这样它就可以被多个组件导入)
interface ProvideType {
  toChildValue: Ref<string>;
  changeValue: () => void;
}
// 为注入值标记类型
const toValue = Symbol() as InjectionKey<ProvideType>

如下为孙子组件DeepChild.vue

<template>
  <div>
    我是deepChild组件
    <div>
      <button @click="changeValue">改变祖先组件的值</button>
      {{toChildValue}}
    </div>
  </div>
</template>

<script setup lang="ts">
import {inject, ref, Ref} from "vue";

// 定义注入值的类型
interface ProvideType {
  toChildValue: Ref<string>;
  changeValue: () => void;
}
// 解构获取父组件传的值,需要进行强制类型转换
const {toChildValue, changeValue} = inject(/* 注入名 */"toValue") as ProvideType
// 不解构时,只需指定类型即可
// const value = inject<ProvideType>(/* 注入名 */"toValue")
</script>

当祖先组件提供参数与方法时,子组件在解构时需要强制转换该值的类型

// 解构获取父组件传的值
const {toChildValue, changeValue} = inject(/* 注入名 */"toValue") as ProvideType

如果子组件在使用时不进行解构,则直接指明类型即可

// 不解构时,直接指定类型即可
const value = inject<ProvideType>(/* 注入名 */"toValue")

参考

1、小满ZS 学习Vue3 第二十三章(依赖注入Provide / Inject) https://blog.csdn.net/qq1195566313/article/details/123143981?spm=1001.2014.3001.5501
2、Vue3官网 依赖注入
https://cn.vuejs.org/guide/components/provide-inject.html文章来源地址https://www.toymoban.com/news/detail-802882.html

到了这里,关于Vue3父子组件间传参通信的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • vue3 常用的组件互相通信(父子、兄弟、爷孙、任意组件)

    目录 前言:目前组件通信方法有好多种,我这挑选一部分来讲 1、父传子 2、子传父 3、兄弟之间通信 3.1、父组件充当中间件 3.2、全局事件总线—EventBus 4、爷孙之间通信 5、任意组件、全局 方案 父传子 子传父 props / emits props emits v-model / emits v-model emits ref / emits ref emits provi

    2024年02月15日
    浏览(30)
  • vue3探索——组件通信之v-model父子组件数据同步

    再很多场景中,我们可能想在子组件中修改父组件的数据,但事实上,vue不推荐我们这么做,因为数据的修改不容易溯源。 在vue2中,我们使用 .sync 修饰符+自定义事件 \\\'update:xxx\\\' ,来使父子组件数据同步。 这里不作过多说明,有需要请自行了解。 vue3的写法与vue2基本一致。最

    2024年02月11日
    浏览(51)
  • vue3探索——使用ref与$parent实现父子组件间通信

    在vue3中,可以使用vue3的API defineExpose() 函数结合 ref 或者 $parent ,实现父子组件数据的传递。 子组件:通过 defineExpose() 函数,向外暴露响应式数据或者方法 父组件:通过 ref 获取子组件实例,进而获取子组件暴露的响应式数据或方法 💡 你没看错!这里的 ref 就是经常用来定

    2024年02月10日
    浏览(33)
  • vue3中监听,组件通信如父子传值、Vuex、Event Bus的使用

    目录 一、监听 二、父子传值: 1、父传子: 2、子传父 三、全局状态管理(Vuex): 四、事件总线(Event Bus): 我们有一个父组件ParentComponent和一个子组件ChildComponent。在父组件中,我们使用:childProp=\\\"parentData\\\"将数据传递给子组件。在子组件中,我们使用defineProps来接收父组件

    2024年02月13日
    浏览(28)
  • Vue3的手脚架使用和组件父子间通信-插槽(Options API)学习笔记

    全局安装最新vue3 升级Vue CLI: 如果是比较旧的版本,可以通过下面命令来升级 通过脚手架创建项目 父组件 子组件 UserComponent.vue 父组件 **子组件1 JiaComponent.vue ** ** 子组件2 JianComponent.vue ** 父组件 子组件 TitleComponents.vue 父组件 **子组件 NavComponent.vue ** 父组件 子组件 NavCompone

    2024年02月05日
    浏览(32)
  • vue3 父子组件传值 记录

    最近这个组件之间传值用的较多,我这该死的记性,总给忘记写法,特此记录下 补充:LeftView.vue 是父组件; Video.vue 是子组件 Video.vue 子组件 LeftView.vue 父组件 第一步 创建bus.js文件 第二步 分别在需要相互传参的组件中引入bus.js文件,并相互传参

    2024年02月11日
    浏览(33)
  • Vue3父子组件相互调用方法

    下面演示均为使用 setup 语法糖的情况! 参考网址:https://cn.vuejs.org/api/sfc-script-setup.html#defineexpose 子组件需要使用defineExpose对外暴露方法,父组件才可以调用! 1.子组件 2.父组件 3.测试结果 1.父组件 2.子组件 3.测试结果 今天的分享就到这里啦~~ 如有错误,欢迎随时雅正。

    2024年02月11日
    浏览(37)
  • vue3父子组件相互调用方法详解

    在vue3项目开发中,我们常常会遇到父子组件相互调用的场景,下面以setup语法糖格式详细聊聊父子组件那些事儿。

    2024年02月11日
    浏览(28)
  • vue3 组件传参

    原理: 通过第三个“东西”,一个往里写,一个读取。 方案:Mitt.js Mitt.js 安装及使用方法 安装 包的官网: https://www.npmjs.com/package/mitt 封装: 在项目src目录下新建一个 bus文件夹,里面再建一个bus.ts文件,用来存放咱们的EventBusa事件总线。在 bus.ts 文件中,封装代码。 简单: 复杂点

    2024年04月26日
    浏览(28)
  • vue父子组件之间双向数据绑定的(vue2/vue3)

    vue父子组件之间双向数据绑定的四种方法(vue2/vue3) vue考虑到组件的可维护性,是不允许子组件改变父组件传的props值的。父组件通过绑定属性的方式向子组件传值,而在子组件中可以通过$emit向父组件通信(第一种方式),通过这种间接的方式改变父组件的data,从而实现子组

    2024年02月08日
    浏览(57)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包