Vue3父子组件间传参通信

02-27 阅读 0评论

Vue3 父子组件间通信

  • 前言
  • 一、父传子 defineProps
  • 二、子传父 defineEmits
  • 三、子组件暴露属性给父组件 defineExpose
  • 四、依赖注入Provide / Inject
  • 参考

    前言

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

    Vue3父子组件间传参通信,Vue3父子组件间传参通信,词库加载错误:未能找到文件“C:\Users\Administrator\Desktop\火车头9.8破解版\Configuration\Dict_Stopwords.txt”。,使用,我们,注册,第1张
    (图片来源网络,侵删)

    Vue3+TypeScript

    一、父传子 defineProps

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

    如下为父组件Father.vue

      
    我是父组件
    import Son from './Son.vue' import {ref} from "vue"; const fatherMessage = ref("我是父组件传过来的值") .fa{ border: 3px solid cornflowerblue; width: 400px; text-align: center; }

    如下为子组件Son.vue

      
    我是子组件
    父组件传值接收区:{{fatherMessage}}
    interface Props { fatherMessage?: string, } defineProps()

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

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

    Vue3父子组件间传参通信,Vue3父子组件间传参通信,词库加载错误:未能找到文件“C:\Users\Administrator\Desktop\火车头9.8破解版\Configuration\Dict_Stopwords.txt”。,使用,我们,注册,第2张
    (图片来源网络,侵删)

    二、子传父 defineEmits

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

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

    如下为子组件Son.vue

      
    我是子组件 传值给父组件
    import {ref} from "vue"; // 定义所要传给父组件的值 const value = ref("我是子组件传给父组件的值") // 使用defineEmits注册一个自定义事件 const emit = defineEmits(["getValue"]) // 点击事件触发emit,去调用我们注册的自定义事件getValue,并传递value参数至父组件 const transValue = () => { emit("getValue", value.value) }

    如下为父组件Father.vue

      
    我是父组件
    父组件接收子组件传的值:{{sonMessage}}
    import Son from './Son.vue' import {ref} from "vue"; const sonMessage = ref("") const getSonValue = (value: string) => { sonMessage.value = value } .fa{ border: 3px solid cornflowerblue; width: 400px; text-align: center; }

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

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

    Vue3父子组件间传参通信,Vue3父子组件间传参通信,词库加载错误:未能找到文件“C:\Users\Administrator\Desktop\火车头9.8破解版\Configuration\Dict_Stopwords.txt”。,使用,我们,注册,第3张
    (图片来源网络,侵删)

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

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

    如下为子组件Son.vue

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

    如下为父组件Father.vue

      
    我是父组件
    获取子组件的方法
    import Son from './Son.vue' import {ref} from "vue"; const sonMethodRef = ref() const getSonMethod = () => { sonMethodRef.value.toFatherMethod() console.log(sonMethodRef.value.toFatherValue) } .fa{ border: 3px solid cornflowerblue; width: 400px; text-align: center; }

    在子组件中定义属性toFatherValue和方法toFatherMethod,而后通过defineExpose暴露出来。

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

    四、依赖注入Provide / Inject

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

    Vue3父子组件间传参通信

    虽然这里的 Footer 组件可能根本不关心这些 props,但为了使 DeepChild 能访问到它们,仍然需要定义并向下传递。如果组件链路非常长,可能会影响到更多这条路上的组件。这一问题被称为“prop 逐级透传”,显然是我们希望尽量避免的情况。

    provide 和 inject 可以帮助我们解决这一问题。 一个父组件相对于其所有的后代组件,会作为依赖提供者。任何后代的组件树,无论层级有多深,都可以注入由父组件提供给整条链路的依赖。

    Vue3父子组件间传参通信

    如下为父组件Root.vue

      
    我是root组件
    import { provide, ref } from 'vue' import Footer from './Footer.vue' const toChildValue= ref("我是给所有子组件的值") // 将toChildValue注入到所有子组件中 provide(/* 注入名 */ 'toChildValue', /* 值 */ toChildValue)

    如下为子组件Footer.vue

      
    我是footer组件
    接收父组件的值:{{getFatherValue}}
    import DeepChild from "./DeepChild.vue" import {ref,inject,Ref} from "vue"; // 获取父组件提供的值 // 如果没有祖先组件提供 "toChildValue" // ref("") 会是 "这是默认值" const getFatherValue = inject(/* 注入名 */"toChildValue",/* 默认值 */ ref(""))

    如下为孙子组件DeepChild.vue

      
    我是deepChild组件
    接收爷爷组件的值:{{getGrandFatherValue}}
    import {inject, ref, Ref} from "vue"; // 获取爷爷组件提供的值 // 如果没有爷爷组件提供 "toChildValue" // value 会是 "" const getGrandFatherValue = inject(/* 注入名 */"toChildValue",/* 默认值 */ ref(""))

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

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

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

    inject(/* 注入名 */"toChildValue",/* 默认值 */ ref(""))
    

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

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

    如下为父组件Root.vue

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

    provide 和 inject 通常会在不同的组件中运行。要正确地为注入的值标记类型,Vue 提供了一个 InjectionKey 接口,它是一个继承自 Symbol 的泛型类型,可以用来在提供者和消费者之间同步注入值的类型。

    建议将注入 key 的类型放在一个单独的文件中,这样它就可以被多个组件导入。

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

    如下为孙子组件DeepChild.vue

      
    我是deepChild组件
    改变祖先组件的值 {{toChildValue}}
    import {inject, ref, Ref} from "vue"; // 定义注入值的类型 interface ProvideType { toChildValue: Ref; changeValue: () => void; } // 解构获取父组件传的值,需要进行强制类型转换 const {toChildValue, changeValue} = inject(/* 注入名 */"toValue") as ProvideType // 不解构时,只需指定类型即可 // const value = inject(/* 注入名 */"toValue")

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

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

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

    // 不解构时,直接指定类型即可
    const value = inject(/* 注入名 */"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


免责声明
本网站所收集的部分公开资料来源于AI生成和互联网,转载的目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。
文章版权声明:除非注明,否则均为主机测评原创文章,转载或复制请以超链接形式并注明出处。

发表评论

快捷回复: 表情:
评论列表 (暂无评论,人围观)

还没有评论,来说两句吧...

目录[+]