typescript - VUE 3 传递 prop 到 watch composition API

标签 typescript vue.js vuejs3 vue-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 是文字值(非 react 性)。用 ref 包装文字值不会恢复 props 的 react 性,而是创建一个新的独立 ref

要保持可组合项的 react 性,请使用 toRefstoRef获取 barcodePulse:

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

usePulse(barcodePulse)

demo

关于typescript - VUE 3 传递 prop 到 watch composition API,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69443032/

相关文章:

javascript - 仅在 Vue 中填写字段后提交表单

php - 参数 1 使用 Axios Vue 和 Laravel 7 传递给 Symfony\Component\HttpFoundation\Response::setContent()

vue.js - Vue 3 外部组件/插件在运行时加载

javascript - vue 3 import vue-tables-3 但我收到错误 : "_vue.default is not a constructor"

javascript - 为什么当我将 axios.get() 数据传递给响应式对象 vuejs 时,我无法访问它?

javascript - typescript 自动序列化类实例?

typescript - 组件装饰器的 vue-loader 解析错误

javascript - 如何通过重新排列列来创建 vuetify 数据表?

arrays - 如果条件匹配, typescript 数组删除项目

javascript - Typescript - 类型 'string' 不可分配给类型 'boolean'