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, }; }
问题分析
- 数据引用不一致:
useFilters中调用useRooms()会生成新的Roomsref实例,与Rooms组件中使用的不是同一个引用,导致数据更新无法同步。 - Ref取值错误:直接使用
filtersOptions._value访问ref值,Vue3中应通过.value访问,_value是内部私有属性,不可直接调用。 - 跨域请求头错误:
Access-Control-Allow-*是后端响应头,前端请求无需添加这些字段。 - 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()每次调用都会返回同一个Roomsref实例,确保Filters组件更新数据后,Rooms组件能实时响应。 - 响应式更新:Rooms组件通过
v-for遍历Roomsref,当Rooms.value被赋值为新数组时,Vue3的响应式系统会自动触发组件重新渲染。 - 错误处理:添加了日期校验和HTTP错误捕获,提升用户体验和调试效率。
内容的提问来源于stack exchange,提问作者leesek
相关产品推荐
相关产品推荐

