Vue3 + TypeScript中如何读取父组件属性?
Vue3 + TypeScript 子组件无法获取父组件state属性问题
我在编写子组件AccordionPane时,需要获取父组件AccordionControl的state属性,但注释的代码无法生效,state变量始终为null。父组件的getProps计算属性显示state prop已正确定义,但网上TypeScript相关示例较少,难以直接从JavaScript示例适配。
类型定义
export type AccordionKeys = "open" | "disabled"; export type AccordionState = { [key: string]: {[key in AccordionKeys]: boolean; }; }
子组件 AccordionPane 代码
<script lang="ts"> import { AccordionState } from "@/types/global"; import { defineComponent, useAttrs } from "vue"; export default defineComponent({ name: "AccordionPane", props: { panelName: { type: String, required: true, }, }, computed: { open(): boolean { // const attrs = useAttrs(); // const state = attrs.state as AccordionState; // return state[this.panelName].open && !state[this.panelName].disabled; return true; }, disabled(): boolean { // const attrs = useAttrs(); // const state = attrs.state as AccordionState; // return state[this.panelName].disabled; return false; }, } }); </script>
父组件 AccordionControl 代码
<template> <div class="accordionControl"> <slot ref="content"></slot> </div> <textarea class="debug" v-model="getProps"></textarea> </template> <script lang="ts"> import { type AccordionState } from '@/types/global'; import { defineComponent, type PropType } from 'vue'; export default defineComponent({ name: "AccordionControl", props: { state: { type: Object as PropType<AccordionState>, required: true, }, isVert: { type: Boolean, default: false, }, allOpen: { type: Boolean, default: false, } }, computed: { getProps(): string { return JSON.stringify(this.$props, null, ' '); } } }); </script>
问题原因与解决方法
问题根源
你试图通过useAttrs()获取父组件的state,但useAttrs()仅能获取传递给当前组件的非props属性。而父组件的state是自身的props,并没有传递给插槽内的子组件,因此子组件自然拿不到该值。
解决步骤
1. 修改父组件,通过作用域插槽传递state
在父组件的插槽中,将自身的state作为插槽props传递出去:
<template> <div class="accordionControl"> <!-- 将state作为插槽props传递给子组件 --> <slot ref="content" :state="state"></slot> </div> <textarea class="debug" v-model="getProps"></textarea> </template>
2. 子组件定义state props并接收
子组件显式定义state为props,直接从父组件传递的属性中获取值:
<script lang="ts"> import { AccordionState } from "@/types/global"; import { defineComponent, type PropType } from "vue"; export default defineComponent({ name: "AccordionPane", props: { panelName: { type: String, required: true, }, // 添加state props定义 state: { type: Object as PropType<AccordionState>, required: true, }, }, computed: { open(): boolean { return this.state[this.panelName].open && !this.state[this.panelName].disabled; }, disabled(): boolean { return this.state[this.panelName].disabled; }, } }); </script>
3. 在父组件插槽中传递state给子组件
使用AccordionControl时,通过插槽props接收state并传递给AccordionPane:
<AccordionControl :state="yourAccordionState"> <template #default="{ state }"> <AccordionPane panelName="panel1" :state="state" /> <AccordionPane panelName="panel2" :state="state" /> </template> </AccordionControl>
这样修改后,子组件就能正确获取到父组件的state属性,计算属性也能正常工作。
内容的提问来源于stack exchange,提问作者GeeWhizBang
相关产品推荐
相关产品推荐

