VUE 3 Pass prop to watch composition API

VUE 3 Pass prop to watch composition API

我正在为 Vue 3 组合而苦苦挣扎 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 or toRef 获取 barcodePulse:

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

usePulse(barcodePulse)

demo