功能
- 串接 api 拿到資料,
- 在搜尋欄中輸入關鍵字後,下方顯示包含此關鍵字的城市或州名以及其人口數
- 顯示時,關鍵字底部要有顏色(#ffc600),人口數後面數來每 3 個數字前加 1 個 comma
step 1 : 用 Fetch API 取得城市的資料
// api 位置
const endpoint = 'https://gist.githubusercontent.com/Miserlou/c5cd8364bf9b2420bb29/raw/2bf258763cdddd704f8ffd3ea9a3e81d25e2c6f6/cities.json';
// 建立空陣列 - 準備接 api 傳來的資料
const cities = []
// 串接 api -fetch 方法
fetch(endpoint)
// 由於 fetch 會回傳 Promise,把第一個回傳解析成 json 格式,讓下一個 callback 中使用:
.then(blob => blob.json())
// cities 是 const,無法再賦值,這邊 push() 把資料丟進去, ...data,這邊是用 ES6 的展開運算子,
.then(data => cities.push(...data))
// 串接 api - XMLHttpRequest 方法
// const request = new XMLHttpRequest()
// request.open('GET', endpoint, true)
// request.onload = function() {
// if (request.status >= 200 && request.status < 400) {
// const data = JSON.parse(request.responseText)
// cities.push(...data)
// }
// }
// request.send()
step 2 : 建立 findMatches 函式,比對城市名或州名裡是否包含關鍵字
// 建立函式 - 比對資料的 city 或 state 是否與關鍵字相符
function findMatches(wordToMatch, cities){
// filter() 篩選符合條件的資料
return cities.filter( place => {
// 用 RegExp 建立篩選條件
const regex = new RegExp(wordToMatch,'gi')
// 用 match() 比對後,回傳符合篩選條件的城市名或州名
return place.city.match(regex) || place.city.match(regex)
})
}
step 3 : 監聽搜尋欄 input 的值
// 取得 '搜尋欄 input'與 '結果顯示列表'的 DOM,並監聽 input 的有輸入且停止輸入的事件, 事件發生時執行 displayMatches
const searchInput = document.querySelector('.search')
const suggestions = document.querySelector('.suggestions')
searchInput.addEventListener('change',displayMatches)
searchInput.addEventListener('keyup', displayMatches)
step 4 : 建立 displayMatches 函式,找到與搜尋欄內關鍵字相符的資料並顯示出來
// 建立函式 - 找到與搜尋欄內關鍵字相符合的 city 或 state 名稱,帶入結果顯示的 DOM 元素中
function displayMatches(){
// 取得搜尋欄 input 內的值
let inputValue = searchInput.value
// 查找並回傳與搜尋欄 input 內的值比對後,符合的資料
let matchArray = findMatches(inputValue, cities)
// 將每筆資料處理後,傳回 HTML
let html = matchArray.map(place =>{
// 設定符合條件為輸入的關鍵字
let regex = new RegExp(inputValue, 'gi')
// 把城市名中包含關鍵字的部分加 class = "hl",改變關鍵字的背景色
let cityName = place.city.replace(regex, `<span class="hl">${inputValue}</span>`)
// 把州名中包含關鍵字的部分加 class = "hl",改變關鍵字的背景色
let stateName = place.state.replace(regex, `<span class="hl">${inputValue}</span>`)
//用 map() 會得到一個新的 array,因為要放入 html,因此用 join('') 將 array 內的每項都用''(空字串) 串起來 innerHTLML 渲染到網頁上
return `
<li>
<span class="city">${cityName}, ${stateName}</span>
<span class="population">${numberWithCoommas(place.population)}</span>
</li>
`
}).join('')
// 再將 html 帶入 suggestion 的 innerHTML 中,渲染在網頁上
suggestions.innerHTML = html
}
step 5 : 建立 numberWithCoommas 函式,以符合所要求的人口數格式
// 建立函式 - 後面數來每三位數字加一個 comma
function numberWithCoommas(x){
return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g,',')
}
CSS
排序為第奇數個的 child : nth-child(odd)
排序為第偶數個的 child : nth-child(even)
RegExp()
建立正規式 new RegExp(regex, flag)
來:
第一個參數是正規式的內容
第二個參數是 flag
- g 表示 global search,=> 尋找整份文件有包含的,而不是找到就停
- i 表示 case insensitive =>不區分大小寫
參考資料: