專案介紹: 用 fetch 去 get 城市資料,並用正規表達式來回傳搜尋相關程式
作品頁面:https://iris1114.github.io/javascript30/06_Type-Ahead/index.html
做法:
- fetch 取得城市資料
- 取得輸入的值並用 regex 與城市資料的 city 及 state 做對比
- 用 filter 取得對比成功的值,並回傳新陣列
- 用此篩選好的新陣列再去呈現畫面
fetch & ajax
fetch 取得 json 資料:
1let cities = null;2fetch(endpoint)3 .then((res) => {4 return res.json();5 })6 .then((res) => {7 cities = res;8 });
若是用 ajax 做法:(太久沒用 複習一下 XD)
1function requestHandle() {2 console.log(JSON.parse(this.response));3}45let req = new XMLHttpRequest();6req.addEventListener("load", requestHandle);7req.open("get", endpoint);8req.send();
正規表示法 Regular Expressions
正規表示法 (Regex) 是用來處理字串的方法,Regex 用自己一套特殊的符號表示法,讓我們可以很方便的搜尋字串、取代字串、刪除字串或測試字串是否符合樣式規則。
1const findMatches = (wordToMatch, cities) => {2 return cities.filter((place) => {3 const regex = new RegExp(wordToMatch, "gi");4 return place.city.match(regex) || place.state.match(regex);5 });6};
- RegExp() 物件用來建立正規式:第一個參數是正規式的內容,第二個參數是 flag。
- g 表示 Global search,尋找整份文件,而不會找到就停。
- i 表示 Case insensitive,表示不區分大小寫。
- match() 方法可在字符串内找到指定的値,或找到一个或多個正規式的匹配。
1function numberWithCommas(x) {2 return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");3}
設定一個 numberWithCommas() 的方法,用於表達千分位。
\B(?=(\d{3})+(?!\d))
是千分位的正規式。\d{3}
匹配 3 個數字,+表示前面的内容重複 1 到多次,所以(\d{3})+
表示三個數字的 1 到多次,也就是 3,6,9…等 3 的倍數個數字的字串(?!\d)
匹配一个位置,此位置後面不是數字(?=(\d{3})+(?!\d))
匹配一个位置,這個位置後面首先是 3 的倍數個數字的字串,接下来的位置不是數字/\B(?=(\d{3})+(?!\d))/g
就是全部匹配一个位置,這個位置前面要有字元存在,然後後面是 3 的倍數個數字,再後面是非數字。
replace() 、 match()
replace() 方法會傳回一個新字串,此新字串是透過將原字串與 pattern 比對,以 replacement 取代吻合處而生成。pattern 可以是字串或 RegExp,而 replacement 可以是字串或函式(會在每一次匹配時被呼叫)。
syntax: str.replace(regexp|substr, newSubstr|function)
範例
1var str = "Twas the night before Xmas...";2var newstr = str.replace(/xmas/i, "Christmas");3console.log(newstr); // Twas the night before Christmas...
match()方法檢索返回一個字符串匹配正則表達式的結果。
syntax: str.match(regexp)
範例
1var str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";2var regexp = /[A-E]/gi;3var matches_array = str.match(regexp);45console.log(matches_array);6// ['A', 'B', 'C', 'D', 'E', 'a', 'b', 'c', 'd', 'e']
Code
1(() => {2 const endpoint =3 "https://gist.githubusercontent.com/Miserlou/c5cd8364bf9b2420bb29/raw/2bf258763cdddd704f8ffd3ea9a3e81d25e2c6f6/cities.json";45 let cities = null;6 fetch(endpoint)7 .then((res) => {8 return res.json();9 })10 .then((res) => {11 cities = res;12 });1314 //根據輸入字串filter符合city或place的結果15 const findMatches = (wordToMatch, cities) => {16 return cities.filter((place) => {17 const regex = new RegExp(wordToMatch, "gi");18 return place.city.match(regex) || place.state.match(regex);19 });20 };2122 //將人口數量進行千分位的表達23 function numberWithCommas(x) {24 return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");25 }2627 //將符合的值呈現至畫面28 function handleChange() {29 const matchArray = findMatches(this.value, cities);3031 const html = matchArray32 .map((place) => {33 const regex = new RegExp(this.value, "gi");34 const cityName = place.city.replace(35 regex,36 `<span class="hl">${this.value}</span>`37 );38 const stateName = place.state.replace(39 regex,40 `<span class="hl">${this.value}</span>`41 );42 return `43 <li>44 <span class="name">${cityName}, ${stateName}</span>45 <span class="population">${numberWithCommas(place.population)}</span>46 </li>47`;48 })49 .join("");50 suggestions.innerHTML = html;51 }5253 const search = document.querySelector(".search");54 const suggestions = document.querySelector(".suggestions");5556 search.addEventListener("input", handleChange);57})();
參考資料
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/match https://ithelp.ithome.com.tw/questions/10195924 https://blog.epoch.tw/ https://developer.mozilla.org/zh-TW/docs/Web/JavaScript/Reference/Global_Objects/String/replace