You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vue3组件如何根据接口返回数据更新内容?

Vue3 酒店预订筛选组件数据更新问题

我正在基于.NET + Vue3开发酒店预订服务的筛选功能,后端筛选接口运行正常,但组件无法根据获取到的数据更新内容。

接口返回数据格式

接口返回包含房间信息的数组,每个房间对象包含Id、Name、Price等核心字段。

现有代码文件

Filters组件

<template>
    <div class="container">
        <div class="d-flex align-items-center">
            <label for="first_day" class="p-2">First day: </label>
            <input type="date" name="first_day" v-model="filtersOptions.FirstDay" />

            <label for="last_day" class="p-2">Last day: </label>
            <input type="date" name="last_day" v-model="filtersOptions.LastDay"/>
            <button type="submit" class="m-2 p-2" v-on:click="fetchFilteredRooms()">Search</button>
        </div>
    </div>
</template>

<script lang="ts">
import { useFilters } from '@/composables/useFilters';
export default {
    setup(props: any, context: any) {
        const { filtersOptions, fetchFilteredRooms } = useFilters();

        return {
            filtersOptions,
            fetchFilteredRooms,
        }
    }
}
</script>

Filters脚本(useFilters.ts)

import { ref } from 'vue';
import Consts from "@/consts";
import { useRooms } from './useRooms';

class FiltersOptions {
    FirstDay: any;
    LastDay: any;
};

const { Rooms } = useRooms();

export const useFilters = () => {
    const filtersOptions = ref<any>(new FiltersOptions());

    async function fetchFilteredRooms() {
        const filterRoomsAPI = Consts.API.concat(`rooms/search`)
        const headers = {
            'Content-type': 'application/json; charset=UTF-8',
            'Access-Control-Allow-Methods': 'POST',
            'Access-Control-Allow-Origin': `${filterRoomsAPI}`
        }

        fetch(filterRoomsAPI, {
            method: 'POST',
            mode: 'cors',
            credentials: 'same-origin',
            body: JSON.stringify(filtersOptions._value),
            headers
        })
        .then(response => response.json())
        .then((data) => (Rooms.value = data))
        .catch(error => console.error(error));
    }

    return {
        Rooms,
        filtersOptions,
        fetchFilteredRooms,
    }
}

Rooms组件(原代码粘贴错误,应为房间列表渲染组件)

// 注:原代码与Filters脚本重复,推测应为房间列表组件,正确示例见下文解决方案

Rooms脚本(useRooms.ts)

import { ref } from 'vue';
import Consts from "@/consts"

const headers = {
    'Content-type': 'application/json; charset=UTF-8',
    'Access-Control-Allow-Methods': 'GET',
    'Access-Control-Allow-Origin': `${Consts.RoomsAPI}`
}

export function useRooms() {
    const Rooms = ref([]);

    async function fetchRooms() {
        fetch(Consts.RoomsAPI, { headers })
        .then(response => response.json())
        .then((data) => (Rooms.value = data))
        .catch(error => console.log(error));
    }

    return {
        Rooms,
        fetchRooms,
    };
}

问题分析

  1. 数据引用不一致:useFilters中调用useRooms()会生成新的Rooms ref实例,与Rooms组件中使用的不是同一个引用,导致数据更新无法同步。
  2. Ref取值错误:直接使用filtersOptions._value访问ref值,Vue3中应通过.value访问,_value是内部私有属性,不可直接调用。
  3. 跨域请求头错误:Access-Control-Allow-*是后端响应头,前端请求无需添加这些字段。
  4. Rooms组件代码错误:原代码与Filters脚本重复,未实现房间列表渲染逻辑。

解决方案

1. 修正Filters脚本(useFilters.ts)

import { ref } from 'vue';
import Consts from "@/consts";
import { useRooms } from './useRooms';

class FiltersOptions {
    FirstDay: string | null = null;
    LastDay: string | null = null;
};

// 复用全局共享的Rooms实例
const { Rooms } = useRooms();

export const useFilters = () => {
    const filtersOptions = ref<FiltersOptions>(new FiltersOptions());

    async function fetchFilteredRooms() {
        if (!filtersOptions.value.FirstDay || !filtersOptions.value.LastDay) {
            console.warn("请选择完整的日期范围");
            return;
        }

        const filterRoomsAPI = Consts.API.concat(`rooms/search`);
        const headers = {
            'Content-type': 'application/json; charset=UTF-8'
        };

        try {
            const response = await fetch(filterRoomsAPI, {
                method: 'POST',
                mode: 'cors',
                credentials: 'same-origin',
                body: JSON.stringify(filtersOptions.value), // 修正为.value
                headers
            });
            
            if (!response.ok) throw new Error(`请求失败: ${response.status}`);
            const data = await response.json();
            Rooms.value = data;
        } catch (error) {
            console.error("筛选房间失败:", error);
        }
    }

    return {
        filtersOptions,
        fetchFilteredRooms,
    }
}

2. 修正Rooms组件(Rooms.vue)

<template>
  <div class="rooms-container mt-4">
    <div class="row">
      <div v-for="room in Rooms" :key="room.Id" class="col-md-4 mb-3">
        <div class="card">
          <div class="card-body">
            <h5 class="card-title">{{ room.Name }}</h5>
            <p class="card-text">价格: {{ room.Price }} 元/晚</p>
            <p class="card-text">房型: {{ room.Type }}</p>
            <p class="card-text" v-if="room.MaxGuests">最多容纳: {{ room.MaxGuests }}人</p>
          </div>
        </div>
      </div>
    </div>
    <div v-if="Rooms.length === 0" class="text-center py-5">
      暂无符合条件的房间
    </div>
  </div>
</template>

<script lang="ts">
import { useRooms } from '@/composables/useRooms';
import { onMounted } from 'vue';

export default {
  name: 'Rooms',
  setup() {
    const { Rooms, fetchRooms } = useRooms();

    // 组件挂载时加载初始房间数据
    onMounted(() => {
      fetchRooms();
    });

    return {
      Rooms
    }
  }
}
</script>

3. 简化Rooms脚本(useRooms.ts)

import { ref } from 'vue';
import Consts from "@/consts"

export function useRooms() {
    const Rooms = ref([]);

    async function fetchRooms() {
        try {
            const response = await fetch(Consts.RoomsAPI, {
                headers: {
                    'Content-type': 'application/json; charset=UTF-8'
                }
            });
            
            if (!response.ok) throw new Error(`请求失败: ${response.status}`);
            const data = await response.json();
            Rooms.value = data;
        } catch (error) {
            console.error("加载房间列表失败:", error);
        }
    }

    return {
        Rooms,
        fetchRooms,
    };
}

关键说明

  • 共享状态同步:ES模块是单例模式,useRooms()每次调用都会返回同一个Rooms ref实例,确保Filters组件更新数据后,Rooms组件能实时响应。
  • 响应式更新:Rooms组件通过v-for遍历Rooms ref,当Rooms.value被赋值为新数组时,Vue3的响应式系统会自动触发组件重新渲染。
  • 错误处理:添加了日期校验和HTTP错误捕获,提升用户体验和调试效率。

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 00:45:42