iT邦幫忙

第 12 屆 iT 邦幫忙鐵人賽

DAY 9
2
Modern Web

實作經典 JavaScript 30系列 第 9

Day09: Ajax Type Ahead with fetch()(二)

WES BOS系列影片
Alex快速導讀系列影片

再來,進入學習的第二個重點部分-
嘗試利用正規表達式來篩選資料
在此之前,先將前置作業完成
1.先抓出需要設置監聽器與更改的元素區塊

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

2.對searchInput設置監聽器

  searchInput.addEventListener("change", '先留空');
  searchInput.addEventListener("keyup", '先留空');

3.製作需要的函式
第一步:依據searchInput 輸入的條件,篩選出符合的資料

function findMatches(wordToMatch, cities) {
    return cities.filter((place) => {
      const regex = new RegExp(wordToMatch, "gi");
      return place.city.match(regex) || place.state.match(regex);
    });
}

這裡用到了之前練習的filter()
來過濾cities這筆陣列,我們需要給filter篩選的條件

正規表達式出場
因為是需要更動的變數,所以需要使用建構子函式帶入匹配的字串
對正規表達式有興趣可以稍微看看這篇。
[JS] 正則表達式(Regular Expression, regex)

const regex = new RegExp(wordToMatch, "gi");

/.../g: global 的意思,找到之後會繼續往後配對
/.../i: case insensitive 的意思,不論大小寫都接受

定義出要匹配的條件後,在filter內遍歷cities中的每一個物件中,
city與state的值,若符合正規表達式定義的條件,就回傳為一個新的陣列。

第二步:將符合的資料用JS寫入Html
先設定好一個簡單的函式內容,並確定監聽器可以觸發這個函式

function displayMatches() {
  console.log(this.value)
}

監聽器綁上函式

searchInput.addEventListener('change', displayMatches);
searchInput.addEventListener('keyup', displayMatches);

當searchInput有發生change或者keyup事件,
都會觸發displayMatches這個函式,也因此,我們可以得到使用者在輸入的條件。
於是就可以套用剛剛做好的findMatches()函式,得到篩選好的陣列

function displayMatches() {
  const matchArray = findMatches(this.value, cities);
  console.log(matchArray)
}

接下來就是將過濾好的陣列拆解後,放入html中

function displayMatches() {
  const matchArray = findMatches(this.value, cities);
  const html = matchArray.map((place) => {
    return `
    <li>
      <span class="name">${place.city},${place.state}</span>
      <span class="population">${place.population}</span>
    </li>
    `
  })
  console.log(html)
}

印出目前的html,發現還是陣列的形式,在這裡就利用join()
將陣列轉成字串,並把做好的html,放進suggestions區塊中。

function displayMatches() {
  const matchArray = findMatches(this.value, cities);
  const html = matchArray.map((place) => {
    return `
    <li>
      <span class="name">${place.city},${place.state}</span>
      <span class="population">${place.population}</span>
    </li>
    `
  }).join('')
  suggestions.innerHTML = html
}

基本上已經完成90%了,但還要做得更細緻一點。
1.符合查詢條件的字都要加上黃色的背景色
正規表達式又有第二招可以用了,
這招是要用正規表達式挑出需要替換成有背景色的字元

function displayMatches() {
  const matchArray = findMatches(this.value, cities);
  const html = matchArray.map((place) => {
    const regex = new RegExp(this.value, 'gi');
    const cityName = place.city.replace(regex, `<span class="hl">${this.value}</span>`)
    const stateName = place.state.replace(regex, `<span class="hl">${this.value}</span>`);
    return `
    <li>
      <span class="name">${cityName},${stateName}</span>
      <span class="population">${place.population}</span>
    </li>
    `
  }).join('');
  suggestions.innerHTML = html;
}

2.population(人口數)要3位數一個逗點
先設定將數字轉換3位數一個逗點的函式,再將人口數丟入這個函式中

function numberWithCommas(x) {
  return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
  }
function displayMatches() {
    ...
    return `
    <li>
      <span class="name">${cityName},${stateName}</span>
      <span class="population">${numberWithCommas(place.population)}</span>
    </li>
    `
  }).join('');
  suggestions.innerHTML = html;
}

今天的練習完成囉,完整的程式碼請直接點擊下方codePen連結
codePen
或者也可以直接到WES BOS的網站下載打包好的檔案
javascript30


上一篇
Day08: Ajax Type Ahead with fetch() (一)
下一篇
Day10: 針對陣列的操作練習(三)
系列文
實作經典 JavaScript 3030

尚未有邦友留言

立即登入留言