تایپاسکریپت - VUE 3 ارسال prop به watch در Composition API


من در کار با Vue 3 Composition API مشکل دارم. من سعی دارم کدم را بر اساس نگرانیهای منطقی تقسیم کنم و نمیتوانم بفهمم چگونه یک ویژگی را برای مشاهده در یک تابع ترکیبی منتقل کنم.

این جزء است:

export default defineComponent({
  props: {
    collapseY: {
      type: Boolean,
      required: false,
      default: false
    },
    barcodePulse: {
      type: Boolean,
      required: false,
      default: false
    }
  },
  setup(props) {
    const pulse = ref(props.barcodePulse)
    const {getRandomVerticalScaleValue, getRandomAnimationDuration} = usePulse(pulse)

    return {
      getRandomVerticalScaleValue,
      getRandomAnimationDuration
    }
  }
})

و این تابع ترکیبی usePulse است:

export interface usePulseData {
    getRandomVerticalScaleValue: () => number;
    getRandomAnimationDuration: () => number;
}

export const usePulse: (pulse: Ref<boolean>) => usePulseData = (pulse) => {
    const stopBarcodeAniation = (event: Event) => {
        (event.target as Element).classList.remove('MY:brand-logo:bar-code:pulse');
        (event.target as Element).removeEventListener('animationiteration', stopBarcodeAniation);
    }

    watch(pulse, (value) => {
        console.log("Prop change")
        const rectangles = document.querySelectorAll('.MY\\:brand-logo\\:bar-code\\:rectangle')
        if (value) {
            for (let index = 0; index < rectangles.length; ++index) {
                rectangles[index].classList.add('MY:brand-logo:bar-code:pulse')
            }
        } else {
            for (let index = 0; index < rectangles.length; ++index) {
                rectangles[index].addEventListener('animationiteration', stopBarcodeAniation)
            }
        }
    })

    const getRandomVerticalScaleValue: () => number = () => {
        return (Math.floor(Math.random() * (10 - 4 + 1) + 4) * 0.1) - 0.1;
    }

    const getRandomAnimationDuration: () => number = () => {
        return Math.floor(Math.random() * (20 - 10 + 1) + 10) * 0.15
    }


    onMounted(() => {
        const rectangles = document.querySelectorAll('.MY\\:brand-logo\\:bar-code\\:rectangle')
        for (let index = 0; index < rectangles.length; ++index) {
            (rectangles[index] as HTMLElement).style.setProperty('--animation-duration', `${getRandomAnimationDuration()}s`);
            (rectangles[index] as HTMLElement).style.setProperty('--scale-factor', `${getRandomVerticalScaleValue()}`);
        }
    })

    return {
        getRandomVerticalScaleValue,
        getRandomAnimationDuration
    } as usePulseData
}

کد console.log('Prop changed') در قطعه کد دوم به دلایلی اجرا نمیشود.

آیا کسی از شما میتواند توضیح دهد چرا این اتفاق نمیافتد؟

پاسخ شماره ۱

مشکل در کد زیر است:

const pulse = ref(props.barcodePulse) // ❌ loses props reactivity

usePulse(pulse)

«props» یک شیٔ «reactive» است، اما «props.barcodePulse» یک مقدار ثابت (غیرواکنشی) است. پیچیدن مقدار ثابت با «ref» واکنشپذیری را از «props» بازیابی نمیکند، بلکه یک «ref» مستقل جدید ایجاد میکند.

برای حفظ واکنشپذیری در کامپوزابل، از toRefs یا toRef برای دریافت barcodePulse استفاده کنید:

const { barcodePulse } = toRefs(props) // ✅
// or
const barcodePulse = toRef(props, 'barcodePulse') // ✅

usePulse(barcodePulse)

نمونه