iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 6
0
Modern Web

寫JS30天系列 第 6

JS 30 - 06 - Ajax Type Ahead

Demo

首先到公眾運輸平台找 api

let flights = [];
fetch(flightApi)
    .then(blob => {
        return blob.json();
    })
    .then(data => {
        flights = data;
    });

fetch()是一個可以將 api 給抓下來的方法,更早以前是使用XMLHttpRequest, XMLHttpRequest 可以讓用戶不必重新請求整個網頁,而是只重新渲染其中的一部分

fetch()可以讓我們在索取遠端伺服器的資料同時,去跑接下來的程式碼
非同步的語言在向遠端伺服器要資料的同時
會繼續跑之後的程式碼
所以被稱為非同步

而同步的語言則是一行一行跑程式碼
這會導致在根遠端伺服器請求資料的同時
會一直卡著不動,等到資料請求完畢,才會繼續執行程式碼
這會導致用戶體驗差

fetch(url)回來的東西會是一個promise
然後使用.then()來取得的資料

.thenpromise的一個 method ,在 fetch 取得檔案後要程式做的事情

我們使用第一個.then方法回傳的還是一個promise物件
其內有我們所需要的航班資訊使用.json將之轉成 json 檔
最後再將這些資料(這裡是物件)放到flights array 內

接著我們要來監聽 input 事件, 只要 input 內容有更動就會觸發事件

const searchInput = document.querySelector('.search');
const suggestions = document.querySelector('.suggestions');

searchInput.addEventListener('input', displayMatches);

監聽好後,要來找符合要求的字了,我們要傳出符合要求的「航空公司 ID 」「班機號碼」和「機場 ID 」,但在這之前要先去了解一下正則表達式

正則表達式

之前做的筆記,正則表達式

我們將陣列 flights 用 .filter()篩選,並要符合正則表達式的要求字串才會被 return

match()

match()也是 string 的 method,.match(regex)表示字串要符合所規範的正則表達式才會留下

function findMatches(wordToMatch, flights) {
    return flights.filter((flight) => {
        const regex = new RegExp(wordToMatch, 'gi');
        return (`${flight.AirlineID}${flight.FlightNumber}`).match(regex) || flight.ArrivalAirportID.match(regex);
    });
};

接著用 matchArr 去裝剛剛成功篩選出的字串,我們希望 match 的字要被 highlight 起來,
所以還要對 matchArr 做修改,得到一個修改過的 Array ,這個描述,就是 .map()。我們要將 match的字用<span class="hl"></span>包起來,這樣就可以吃到 css 特效了。就讓 .replace() 來幫幫我們吧!


function displayMatches() {
    const matchArr = findMatches(this.value, flights);
    const html = matchArr.map(flight => {
        const regex = new RegExp(this.value, 'gi');
        const arrivalAirportId = flight.ArrivalAirportID.replace(regex, `<span class="hl">${this.value}</span>`);
        const flightNumber = (`${flight.AirlineID}${flight.FlightNumber}`).replace(regex, `<span class="hl">${this.value}</span>`);
        const regexT = new RegExp("T", 'gi');
        const scheduleDepartureTime = flight.ScheduleDepartureTime === undefined ? "no-data" : flight.ScheduleDepartureTime.replace(regexT, ' ');
        return `
            <li>
                <span class="flight-number">${flightNumber}</span>
                <span class="schedule-depar-time">${scheduleDepartureTime}</span>
                <span class="airline">${arrivalAirportId}</span>
            </li>
        `
    }).join('');

接著我想要再加個起飛時間!

const scheduleDepartureTime = flight.ScheduleDepartureTime === undefined ? "no-data" : flight.ScheduleDepartureTime.replace(regexT, ' ');

在取得航班表定起飛時間時遇到了一點麻煩
因為並不是每一筆資料都有表定起飛時間
所以如果沒有使用判別式
將會取得兩種資料
2018-08-19T09:10undefind

這時候如果想要將"T"改成" "會在沒有資料的地方出現問題
因為undefined是不被允許使用replace
所以我們要講undefined的資料以"no-data"顯示

最後得到的是一個新的 array ,但是 html 看不懂 array ,他只看得懂字串
所以最後我們再使用 .join('') 讓 array 內的每個項目都用''(空字串)串起來,
再使用 innerHTLML 渲染到網頁上


上一篇
JS 30 - 05 -Flex Panels Image Gallery
下一篇
JS 30 - 07 - Array Cardio Part II
系列文
寫JS30天30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言