Web 前端开发 让前端飞前端开发那些事

[JavaScript30 笔记] 06 - Type Ahea

2017-01-15  本文已影响0人  Dreammlesser

写在系列开篇

在学习了基本的 HTML / CSS / JavaScript 之后没有啥 side project 就直接开始学 Angular 做项目。遇到最近很火的JavaScript30这个项目后决心好好实践一下 Vanilla JavaScript。

对于每个挑战,我会自己在看过视频了解原理后自己实现一遍并在 blog 里记录过程、想法和相关资料。源码放在我的 Github上,demo 通过 Github Pages 部署,点击这里或 Github 的 readme 中连接可以访问。

Objective

实现一个 "typeahead",按下输入字母后搜索缓存数据中匹配的条目并显示。同时高亮搜索的字符串。

demodemo

Steps

  1. ajax 请求数据并缓存;
  2. 添加 keyup 和 change 事件监听器,搜索匹配的条目;
  3. 修改添加 suggestions 的 innerHTML。

Things Learned

fetch API

fetch()是一个新引入的api,用于获取资源并返回一个 Promise 对象。fetch 可以直接接受一个 url 字符串,也可以接受一个 Request 对象。

由于返回的是 Promise,可以使用 .then() 来处理返回值:

const endpoint = 'https://gist.githubusercontent.com/Miserlou/c5cd8364bf9b2420bb29/raw/2bf258763cdddd704f8ffd3ea9a3e81d25e2c6f6/cities.json';
const data = [];

fetch(endpoint)
  .then(res => res.json())
  .then(arr => data.push(...arr));

需要注意的是,fetch 不支持 IE 和 Safari,手机上的支持也不好,所以生产环境中使用还要等待一段时间。

change vs keyup

change 发生的时机是输入的 value 改变并 blur, keyup则是键盘按键松开即触发。

typeahead 设计

搜索并利用 RegExp 替换还是很简单的,我用了 filtermap函数式会简练一点。

function update() {
  const searchStr = this.value.toUpperCase();
  suggestions.innerHTML = data
    .filter(place => 
      place.city.toUpperCase().includes(searchStr) || place.state.toUpperCase().includes(searchStr)
    )
    .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">${numberWithCommas(place.population)}</span>
        </li>
      `; 
    })
    .join('');
}

CSS

Wes 提供的默认 CSS 样式都很好看,这里学习了一下 suggestions 的实现:利用奇偶孩子设置变换角度等和背景的 linear-gradient 实现折叠效果。

.suggestions li:nth-child(even) {
  transform: perspective(100px) rotateX(3deg) translateY(2px) scale(1.001);
  background: linear-gradient(to bottom,  #ffffff 0%,#EFEFEF 100%);
}
.suggestions li:nth-child(odd) {
  transform: perspective(100px) rotateX(-3deg) translateY(3px);
  background: linear-gradient(to top,  #ffffff 0%,#EFEFEF 100%);
}
上一篇下一篇

猜你喜欢

热点阅读