Vue.js 3 render()函数无法在同一父组件中渲染多个Event组件
Vue3 谷歌日历克隆应用渲染问题:同一父元素内重复渲染Event组件仅旧组件更新
我正在使用Vue.js 3开发一款谷歌日历克隆应用。目前遇到的问题是:当尝试使用Vue.js的render()和h()函数在同一父元素内渲染新的Event组件时,只有之前的Event组件会被更新(因修改了其props)。
Calendar.vue (父组件)
<script setup lang="ts"> import { ref, onMounted, computed, watch, h, render, reactive } from "vue"; import Event from "@components/Event.vue"; export interface IEvent { id: number; title: string; description?: string; startDate: Date | null; endDate: Date | null; color?: string; } const CELL_HEIGHT = 40; const eventElementStyles = ref({ position: "absolute", width: "", height: CELL_HEIGHT + "px", backgroundColor: "rgb(141, 224, 141)", zIndex: "100", top: "", left: "", }); const columnElementRefs = ref<HTMLDivElement[] | null>(null); const isClicked = ref<boolean>(false); const indexOfClickedColumn = ref<number>(-1); const newEvent = ref<IEvent>({ id: 1, title: "New Event Title", description: "New Event Description", startDate: null, endDate: null, color: "rgb(141, 224, 141)", }); function resetStyles() { eventElementStyles.value = { position: "absolute", width: "", height: CELL_HEIGHT + "px", backgroundColor: "rgb(141, 224, 141)", zIndex: "100", top: "", left: "", }; } function resetNewEvent() { newEvent.value = { id: 1, title: "New Event Title", description: "New Event Description", startDate: null, endDate: null, color: "rgb(141, 224, 141)", }; } function renderComponent(component, parent, props) { console.log(props); const vueComponent = h(component, props); render(vueComponent, parent); } function handleMousedown( startDate: Date, index: number, rowIndex: number ): void { indexOfClickedColumn.value = index; isClicked.value = true; resetNewEvent(); resetStyles(); newEvent.value.startDate = startDate; newEvent.value.endDate = new Date(startDate.getTime() + 60 * 60_000); eventElementStyles.value.width = `180.58px`; eventElementStyles.value.top = `${rowIndex * CELL_HEIGHT}px`; renderComponent(Event, columnElementRefs.value![index], { styles: eventElementStyles.value, event: newEvent.value, }); } function isPartiallyResizable(colIndex: number): boolean { return isClicked.value && colIndex === indexOfClickedColumn.value; } function canExtendEventTime(colIndex: number, cellDate: Date): boolean { return ( isPartiallyResizable(colIndex) && cellDate.getTime() >= newEvent.value.endDate!.getTime() ); } function canShrinkEventTime(colIndex: number, cellDate: Date): boolean { return ( isPartiallyResizable(colIndex) && cellDate.getTime() < newEvent.value.endDate!.getTime() ); } function getIncreasedEventHeight( oldHeight: number, increaseBy: number ): number { return oldHeight + increaseBy; } function getDecreasedEventHeight( oldHeight: number, decreaseBy: number ): number { return oldHeight - decreaseBy; } function handleMouseover(colIndex: number, cellDate: Date): void { // increase event element height if (canExtendEventTime(colIndex, cellDate)) { newEvent.value.endDate = new Date( newEvent.value.endDate!.getTime() + 60 * 60_000 ); eventElementStyles.value.height = getIncreasedEventHeight( Number(eventElementStyles.value.height.split("px")[0]), CELL_HEIGHT ) + "px"; return; } // decrease event time if (canShrinkEventTime(colIndex, cellDate)) { newEvent.value.endDate = new Date( newEvent.value.endDate!.getTime() - 60 * 60_000 ); eventElementStyles.value.height = getDecreasedEventHeight( Number(eventElementStyles.value.height.split("px")[0]), CELL_HEIGHT ) + "px"; return; } } function handleMouseup(endDate: Date): void { isClicked.value = false; } </script>
Event.vue (子组件)
<template> <div :style="styles" class="eventContainer"> <span class="title">(No title) </span> <span class="times">{{ time }}</span> </div> </template> <script setup lang="ts"> import { IEvent } from "@/pages/Calendar.vue"; import { computed } from "vue"; const { styles, event } = defineProps<{ styles: any; event: IEvent; }>(); const time = computed(() => { return `${extractTimeFromDate(event.startDate!)} - ${extractTimeFromDate( event.endDate! )}`; }); function extractTimeFromDate(date: Date): string { return `${date.getHours().toString().padStart(2, "0")}:${date .getMinutes() .toString() .padStart(2, "0")}`; } </script>
我猜想问题在于始终传递相同的props(eventElementStyles和event),但疑惑为何在不同父元素中渲染组件时功能正常,而在同一父元素中渲染多个组件时仅旧组件会被更新。
内容的提问来源于stack exchange,提问作者Achraf FAWZI
相关产品推荐
相关产品推荐

