VUE 3 Передайте реквизит для просмотра API композиции

#typescript #vue.js #vuejs3 #vue-composition-api

Вопрос:

Я борюсь с API композиции Vue 3. Я пытаюсь разделить свой код по логическим соображениям, и я не могу понять, как передать свойство, которое будет наблюдаться в составной функции.

Это компонент:

 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') Во втором фрагменте кода по какой-то причине не выполняется.

Может ли кто-нибудь из вас объяснить, почему этого не происходит?

Ответ №1:

Проблема заключается в следующем коде:

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

usePulse(pulse)
 

props является reactive объектом, но props.barcodePulse является буквальным значением (нереактивным). Обертывание буквального значения с помощью a ref не восстанавливает реактивность от props , а скорее создает новое независимое ref значение .

Для поддержания реакционной способности в композиционном материале используйте toRefs или toRef для получения barcodePulse :

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

usePulse(barcodePulse)
 

ДЕМОНСТРАЦИЯ