You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多
文档控制台
注册

Vue中更新Proxy Array问题:点击加载更多事件列表

解决事件列表追加时的嵌套与重复问题

问题根源

  • 每次调用useSearchEventsForHomePage传入months=n时,接口返回的是从当前到n个月后的所有事件,包含之前已加载的月份内容,直接追加会导致重复数据。
  • 使用events.value.push(moreEvents.value)会把整个数组作为单个元素推入原数组,形成[[事件1,事件2], [事件1,事件2,事件3,事件4]]的嵌套结构,导致v-for渲染异常。
  • useFetch返回的data是Vue响应式Proxy对象,但核心问题是数组操作逻辑错误,和Proxy本身的工作原理关联不大。

修正方案

1. 调整接口请求逻辑,只请求新增月份的事件

修改useSearchEventsForHomePage,支持指定起始和结束的月份偏移,每次“查看更多”仅请求新增的一个月事件:

export function useSearchEventsForHomePage(startOffsetMonths: number = 0, endOffsetMonths: number = 1) {
  const config = useRuntimeConfig().public;
  const startDate = DateTime.local().plus({ minutes: 1, months: startOffsetMonths }).toUTC().toISO();
  const endDate = DateTime.local().plus({ months: endOffsetMonths }).toUTC().toISO();
  
  const url = `${config.eventApiUrl}/events/search?startDate=${encodeURIComponent(startDate)}&endDate=${encodeURIComponent(endDate)}&summariseDates=false`;

  const options = {
    method: 'GET',
    lazy: true,
    key: url,
    default: () => [],
  };

  return useFetch<Event[]>(url, options);
}

2. 修改页面逻辑,正确追加新增事件

const currentMaxMonths = ref(1);
const events = ref<Event[]>([]);

// 初始化加载第一个月事件
const initEvents = async () => {
  const { data: firstMonthEvents } = await useSearchEventsForHomePage(0, currentMaxMonths.value);
  events.value = firstMonthEvents.value || [];
};
initEvents();

async function seeMore() {
  const prevMaxMonths = currentMaxMonths.value;
  currentMaxMonths.value++;
  // 请求新增的月份区间:从prevMaxMonths到currentMaxMonths
  const { data: moreEvents } = await useSearchEventsForHomePage(prevMaxMonths, currentMaxMonths.value);
  // 用扩展运算符逐个追加新事件,避免嵌套
  if (moreEvents.value) {
    events.value.push(...moreEvents.value);
  }
}

3. 若无法修改接口(只能请求累计月份)

如果接口仅支持返回累计n个月的事件,需过滤重复事件后再追加:

const searchPeriod = ref(1);
const events = ref<Event[]>([]);

// 初始化加载
const initEvents = async () => {
  const { data: firstMonthEvents } = await useSearchEventsForHomePage(searchPeriod.value);
  events.value = firstMonthEvents.value || [];
};
initEvents();

async function seeMore() {
  searchPeriod.value++;
  const { data: moreEvents } = await useSearchEventsForHomePage(searchPeriod.value);
  if (!moreEvents.value) return;
  // 过滤原数组已存在的事件(假设事件有唯一id字段)
  const newEvents = moreEvents.value.filter(event => !events.value.some(e => e.id === event.id));
  // 追加新事件
  events.value.push(...newEvents);
}

关键说明

  • push(...moreEvents.value)替代push(moreEvents.value),可将新数组的每个元素单独推入原数组,彻底避免嵌套问题。
  • 优先选择“请求新增月份”的方案,减少数据传输量和重复处理,性能更优。

内容的提问来源于stack exchange,提问作者maisiemay06

火山引擎 最新活动