如何获取点击航班预订按钮对应的航班数据及解决数组未更新问题
问题分析与解决方案
你的核心问题有两个:
- 异步时机错配:
then链里的console.log(data.flights[data.bookedFlights[0]])是页面渲染完成后立刻执行的,这时用户还没点击预订按钮,bookedFlights数组自然是空的。点击事件是用户触发的异步操作,必须在点击发生后才能获取到数据。 - 数据关联效率低:你现在存的是按钮ID,虽然能通过索引拿到航班,但直接绑定对应航班对象会更直观可靠。
修复后的代码
const fl = fetch("https://mocki.io/v1/fa695c4b-475e-4dfc-8608-952c0c5a28b5"); fl.then((response) => { return response.json(); }).then((result) => { const fakeFlights = result.flights; const table = document.createElement("table"); const thead1 = document.createElement("thead"); const thead2 = document.createElement("thead"); const tbody = document.createElement("tbody"); // 把购物车数组放在这里,确保点击事件能访问到,也方便后续随时调用 const bookedFlights = []; // 构建主表头 let row1 = document.createElement("tr"); let headingTH = document.createElement("th"); headingTH.innerText = "Available Flights"; headingTH.colSpan = 7; row1.appendChild(headingTH); thead1.appendChild(row1); // 构建字段表头 let row2 = document.createElement("tr"); for (let key in fakeFlights[0]) { let heading = document.createElement("th"); // 格式化表头文本 switch(key) { case "flightNumber": heading.innerText = "Flight Number"; break; case "departureTime": heading.innerText = "Departure Time"; break; case "arrivalTime": heading.innerText = "Arrival Time"; break; default: heading.innerText = key; } row2.appendChild(heading); } let bookingHeading = document.createElement("th"); bookingHeading.innerText = "Book the flight"; row2.appendChild(bookingHeading); thead2.appendChild(row2); // 构建航班数据行 for (let i = 0; i < fakeFlights.length; i++) { const flight = fakeFlights[i]; let row = document.createElement("tr"); for (let key in flight) { let rowData = document.createElement("td"); rowData.innerHTML = flight[key]; row.appendChild(rowData); } let btn = document.createElement("button"); btn.innerText = "Book"; // 点击事件直接绑定当前航班对象 btn.addEventListener("click", function() { // 可选:避免重复添加同一航班 if (!bookedFlights.some(item => item.flightNumber === flight.flightNumber)) { bookedFlights.push(flight); // 实时处理购物车逻辑,比如打印或更新页面展示 console.log("已添加航班:", flight); console.log("当前购物车:", bookedFlights); // 更新购物车UI updateCartDisplay(bookedFlights); } else { console.log("该航班已在购物车中"); } }); row.appendChild(btn); tbody.appendChild(row); } table.append(thead1, thead2, tbody); document.body.appendChild(table); // 购物车UI更新函数 function updateCartDisplay(flights) { let cart = document.getElementById("flight-cart"); if (!cart) { cart = document.createElement("div"); cart.id = "flight-cart"; cart.innerHTML = "<h3>购物车</h3>"; document.body.appendChild(cart); } // 清空现有内容后重新渲染 cart.innerHTML = "<h3>购物车</h3>"; flights.forEach((flight, idx) => { let item = document.createElement("div"); item.innerText = `${idx+1}. 航班${flight.flightNumber}: ${flight.departure} → ${flight.arrival}`; cart.appendChild(item); }); } }).catch(() => { document.write("加载航班数据失败") });
关键修改说明
- 异步逻辑修正:把购物车的添加、展示逻辑放在点击事件内部,确保只有用户点击后才执行,避免同步代码提前读取空数组。
- 直接绑定航班数据:循环创建按钮时,直接把当前
flight对象绑定到点击事件中,无需再通过ID索引查找,代码更简洁可靠。 - 新增购物车UI:添加
updateCartDisplay函数,点击按钮后实时更新页面上的购物车展示,满足你的需求。 - 重复添加防护:加入判断逻辑,防止同一航班被多次添加到购物车(可根据需求移除)。
原代码空数组原因
原代码中,你创建完按钮绑定事件后,立刻将bookedFlights放入data对象返回,然后在下一个then里打印数组元素。这整个流程是同步执行的,此时用户还没有任何点击操作,数组自然为空。只有用户点击按钮后数组才会被填充,但这时then链已经执行完毕,所以你看不到后续添加的数据。
内容的提问来源于stack exchange,提问作者LearningCode
相关产品推荐
相关产品推荐

