簡體   English   中英

Vue 3 Composition API - 當父項中的道具發生更改時,計算的子組件未更新

[英]Vue 3 Composition API - Computed child component not updated when props has changed in parent

我在堆棧中使用 Nuxt 3 和 Vue 3。 我希望根據我的父狀態值更改我的組件。 但問題只是我的狀態值改變了,然后子組件中的計算沒有更新。 我已經嘗試將我的道具作為反應性傳遞給其他變量,並直接在 html :class="..." 中移動類綁定,但仍然沒有更新。

這是我的示例代碼:

index.vue - 父組件

<script lang="ts" setup>
import FeaturedIcon from "~/components/icons/FeaturedIcon.vue";

const iconReactive = reactive({
  theme: "light",
  size: "md",
  type: "primary",
});
</script>

<template>
  <div>
    <FeaturedIcon
      :theme="iconReactive.theme"
      :size="iconReactive.size"
      :type="iconReactive.type"
    />

    <button @click="iconReactive.theme = 'dark'">Click Me</button>
  </div>
</template>

精選圖標.vue

<script lang="ts" setup>  
// Props  
import { computed } from "#imports";  
  
interface Props {  
  theme: FeaturedThemeProps;  
  size: FeaturedSizeProps;  
  type: FeaturedTypeProps;  
}  
  
const props = defineProps<Props>();  
  
// * Class state for dynamic styling based on props used  
const defaultClass = {  
  size: {  
  circle: {  
  xs: "h-[24px] w-[24px]",  
      sm: "h-[32px] w-[32px]",  
      md: "h-[40px] w-[40px]",  
      lg: "h-[48px] w-[48px]",  
      xl: "h-[56px] w-[56px]",  
    },  
    icon: {  
  xs: "text-xs",  
      sm: "text-md",  
      md: "text-xl",  
      lg: "text-display-xs",  
      xl: "text-[28px]",  
    },  
  },  
  color: {  
  materialIcon: {  
  primary: "bolt",  
      gray: "bolt",  
      error: "error_outline",  
      warning: "warning_amber",  
      success: "check_circle",  
    },  
  },  
};  
  
const featuredIconClassConfig = {  
  light: {  
  size: {  
  circle: defaultClass.size.circle,  
      icon: defaultClass.size.icon,  
      border: {},  
    },  
    color: {  
  circle: {  
  primary: "bg-primary-100",  
        gray: "bg-gray-100",  
        error: "bg-error-100",  
        warning: "bg-warning-100",  
        success: "bg-success-100",  
      },  
      icon: {  
  primary: "text-primary-700",  
        gray: "text-gray-700",  
        error: "text-error-700",  
        warning: "text-warning-700",  
        success: "text-success-700",  
      },  
      materialIcon: defaultClass.color.materialIcon,  
    },  
  },  
  lightOutline: {  
  size: {  
  circle: defaultClass.size.circle,  
      icon: defaultClass.size.icon,  
      border: {  
  xs: "border-[2px]",  
        sm: "border-[4px]",  
        md: "border-[6px]",  
        lg: "border-[8px]",  
        xl: "border-[10px]",  
      },  
    },  
    color: {  
  circle: {  
  primary: "bg-primary-100 border-primary-50",  
        gray: "bg-gray-100 border-gray-50",  
        error: "bg-error-100 border-error-50",  
        warning: "bg-warning-100 border-warning-50",  
        success: "bg-success-100 border-success-50",  
      },  
      icon: {  
  primary: "text-primary-700",  
        gray: "text-gray-700",  
        error: "text-error-700",  
        warning: "text-warning-700",  
        success: "text-success-700",  
      },  
      materialIcon: defaultClass.color.materialIcon,  
    },  
  },  
  dark: {  
  size: {  
  circle: defaultClass.size.circle,  
      icon: defaultClass.size.icon,  
      border: {  
  xs: "border-[2px]",  
        sm: "border-[4px]",  
        md: "border-[6px]",  
        lg: "border-[8px]",  
        xl: "border-[10px]",  
      },  
    },  
    color: {  
  circle: {  
  primary: "bg-primary-600 border-primary-700",  
        gray: "bg-gray-600 border-gray-700",  
        error: "bg-error-600 border-error-700",  
        warning: "bg-warning-600 border-warning-700",  
        success: "bg-success-600 border-success-700",  
      },  
      icon: {  
        primary: "text-white",  
        gray: "text-white",  
        error: "text-white",  
        warning: "text-white",  
        success: "text-white",  
      },  
      materialIcon: defaultClass.color.materialIcon,  
    },  
  },  
};  
  
const themeSelected = featuredIconClassConfig[props.theme];  
  
const circleDynamicClass = computed(() => {  
  return `${themeSelected.size.circle[props.size]}  
  ${themeSelected.size.border[props.size]}  
  ${themeSelected.color.circle[props.type]}`;  
});  
  
const spanDynamicClass = computed(() => {  
  return `${themeSelected.size.icon[props.size]}  
  ${themeSelected.color.icon[props.type]}`;  
});  
  
const materialIconContent = computed(() => {  
  return `${themeSelected.color.materialIcon[props.type]}`;  
});  
</script>  
  
<template>  
  {{ circleDynamicClass }}  
  <div  
  :class="`flex justify-center items-center rounded-full ${circleDynamicClass}`"  
  >  
 <span :class="`material-icons-outlined inline-block ${spanDynamicClass}`">  
  {{ materialIconContent }}  
    </span>  
 </div>
 </template>
在我更改道具值之前

在此處輸入圖像描述

在此處輸入圖像描述

我只需要在函數中移動themeSelected

const circleDynamicClass = computed(() => {
  const themeSelected = featuredIconClassConfig[props.theme];
  // Do etch
});

當我將它作為外部變量放入時,它沒有重新安裝。 謝謝您的幫助。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM