簡體   English   中英

從呈現的航班列表中,如何訪問與已單擊的航班預訂按鈕相關的特定航班數據?

[英]From a rendered list of flights, how does one access the specific flight-data which relates to the flight's booking-button that has been clicked?

從獲取的航班數據項數組中,我能夠創建一個表格,其中每一行都顯示其特定的航班數據,旁邊還有一個用於預訂相關航班的按鈕。

我想將每個按鈕添加到一個數組中,以便我可以使用該數組來1)訪問當前預訂的航班和2)添加/顯示它到購物車/在購物車上。

我遇到的問題是數組bookedFlights永遠不會被附加,所以我無法訪問已單擊以供稍后使用的按鈕。

如何訪問與已單擊按鈕相關的特定航班數據?

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 bookingButtons = [];
  let row1 = document.createElement("tr");
  let row2 = document.createElement("tr");
  let headingTH = document.createElement("th");
  headingTH.innerText = "Available Flights";
  headingTH.colSpan = 7;
  row1.appendChild(headingTH);
  thead1.appendChild(row1);
  for (key in fakeFlights[0]) {
    let heading = document.createElement("th");
    if (key === "flightNumber") {
      key = "Flight Number"
    }
    if (key === "departureTime") {
      key = "Departure Time"
    }
    if (key === "arrivalTime") {
      key = "Arrival Time"
    }
    heading.innerText = key;
    row2.appendChild(heading);
  }
  let heading = document.createElement("th");
  heading.innerText = "Book the flight";
  row2.appendChild(heading);
  thead2.appendChild(row2);
  for (let i = 0; i < fakeFlights.length; i++) {
    let row = document.createElement("tr");
    for (key in fakeFlights[i]) {
      let rowData = document.createElement("td");
      rowData.innerHTML = fakeFlights[i][key];
      row.appendChild(rowData);
    }
    let btn = document.createElement("button");
    btn.innerText = "Book";
    btn.id = i;
    bookingButtons.push(btn);
    row.appendChild(btn);
    tbody.appendChild(row);
  }
  table.append(thead1, thead2, tbody);
  document.body.appendChild(table);
  let bookedFlights = [];
  for (let selectedButton of bookingButtons) {
    selectedButton.addEventListener("click", function() {
      bookedFlights.push(selectedButton.id);
    });
  }
  const data = {
    flights: fakeFlights,
    bookedFlights: bookedFlights
  }
  return data;
}).then((data) => {
  console.log(data.flights[data.bookedFlights[0]]);
}).catch(() => {
  document.write("error")
});

兩種主要的改進模式/技術是……

  • 事件委托,對於 OP 提供的環境意味着,必須在table相關元素節點或更好的情況下在表體的相關元素節點注冊一個事件偵聽器,因為后者是所有與航班相關的表數據。

  • 關注點分離是另一個。 在其最基本的實現中,針對 OP 最初提供的代碼,這意味着每個正確命名的 function 語句...

    • 獲取( fetchAndDisplayFlightData ),
    • 渲染( createFlightOverview ),
    • 事件處理( handleBookingOfSelectedFlight... ),

    ... 任務。

最終實現具有以下技術/方法......

  • fetchAndDisplayFlightData期望和 URL 從中fetch飛行數據。 在此 function 中,通過將響應數據的flights數組傳遞給 createFlightOverview 來創建航班數據概覽,此處為createFlightOverview表元素。

  • 后者 function 主要通過 OP 最初提供的代碼處理此航班列表( listOfFlights )。 雖然有一些改進,比如......

    • ...使用基於 object 的headerContentLookup以便通過每個數據項的鍵訪問正確的表 header 內容。

    • ...為每個呈現的數據項的“預訂”按鈕使用全局data-*屬性data-flight-number及其相關的dataset屬性flightNumber號,因為后者正是標識航班(或航班數據物品)。

  • 如前所述,只有一個'click'處理程序將在表元素的表體元素中注冊。 非常處理程序 function 實現this上下文感知,因此它期望綁定一個Map 后者的數據由助手 function ( createFlightNumberBasedFlightDataMap ) 創建,它根據每個航班數據項的flightNumber值執行map響應數據的flights數組,該值用作航班項目的標識符key

    • 通過bind臨時創建的已注冊'click'處理程序實現了handleBookingOfSelectedFlightFromBoundFlightDataMap的功能,因此需要一個click事件和此類事件的target 如果其closest的元素與按鈕元素匹配,則可以繼續從該元素的dataset屬性中提取flightNumber 然后,航班號值將用於通過get從查找/地圖訪問相關的航班項目。

    • 在最后一步中,可以將選定的航班數據傳遞給另一個 function,例如 ... bookSelectedFlight(selectedFlightData)

 // - the OP's own originally provided (most of it) table creation code. function createFlightOverview(listOfFlights) { const headerContentLookup = { departureTime: 'Departure Time', arrivalTime: 'Arrival Time', flightNumber: 'Flight Number', destination: 'Destination', origin: 'Origin', price: 'Price', }; const table = document.createElement("table"); const thead1 = document.createElement("thead"); const thead2 = document.createElement("thead"); const tbody = document.createElement("tbody"); // - not needed. // const bookingButtons = []; const row1 = document.createElement("tr"); const row2 = document.createElement("tr"); const headingTH = document.createElement("th"); headingTH.textContent = "Available Flights"; headingTH.colSpan = 7; row1.appendChild(headingTH); thead1.appendChild(row1); Object.keys(listOfFlights[0]).forEach(key => { const heading = document.createElement("th"); heading.textContent = headerContentLookup[key]?? key; row2.appendChild(heading); }); const heading = document.createElement("th"); heading.textContent = "Book the flight"; row2.appendChild(heading); thead2.appendChild(row2); listOfFlights.forEach(flightItem => { const row = document.createElement("tr"); Object.values(flightItem).forEach(value => { const cellData = document.createElement("td"); cellData.textContent = value; row.appendChild(cellData); }); const btn = document.createElement("button"); btn.textContent = "Book"; // - not recommended. // btn.id = i; // - for the flight identification rather use // a data-item's `flightNumber` provided as // global `data-*` attribute... like eg btn.dataset.flightNumber = flightItem.flightNumber; // - not needed. // bookingButtons.push(btn); row.appendChild(btn); tbody.appendChild(row); }); table.append(thead1, thead2, tbody); return table; } // - helper task which creates a `Map` instance from an array of flight // related data-items, based on each item's `flightNumber` value. function createFlightNumberBasedFlightDataMap(listOfFlights) { return new Map( listOfFlights.map(flightItem => [flightItem.flightNumber, flightItem]) ) } // - the final task which actually is going to trigger the // booking-process for the before selected flight-item. function bookSelectedFlight(flightData) { console.log({ selectedFlightData: flightData }); } // - the handler function which is aware of a bound `this` context // where `this` refers to the one time created (and bound) // flight number based lookup. function handleBookingOfSelectedFlightFromBoundFlightDataMap({ target }) { const flightDataMap = this; const elmButton = target.closest('button'); if (elmButton) { const { flightNumber } = elmButton.dataset?? null; const selectedFlightData = flightDataMap.get(flightNumber); console.log({ elmButton, flightNumber/*, selectedFlightData*/ }); bookSelectedFlight(selectedFlightData); } } // - the OP's provided example code changed according to the suggestions. function fetchAndDisplayFlightData(url) { return fetch(url).then(response => response.json()).then(flightData => { const listOfFlights = flightData.flights; const flightOverview = createFlightOverview(listOfFlights); // - register the button specific click-handling at the table's body. flightOverview.querySelector('tbody').addEventListener( 'click', // - create a handler function which has a flight number based // `Map` instance as lookup table bound to its `this` context. handleBookingOfSelectedFlightFromBoundFlightDataMap.bind( createFlightNumberBasedFlightDataMap(listOfFlights) ) ); document.body.appendChild(flightOverview); }).catch(reason => document.body.appendChild(document.createTextNode(String(reason))) ); } fetchAndDisplayFlightData( 'https://mocki.io/v1/fa695c4b-475e-4dfc-8608-952c0c5a28b5' );
 body { margin: 0 0 100px 0; zoom: .9; }.as-console-wrapper { max-height: 100px;important; }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM