#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)