[JavaScript30 笔记] 06 - Type Ahea

作者: Dreammlesser | 来源:发表于2017-01-15 15:44 被阅读0次

    写在系列开篇

    在学习了基本的 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%);
    }
    

    相关文章

      网友评论

        本文标题:[JavaScript30 笔记] 06 - Type Ahea

        本文链接:https://www.haomeiwen.com/subject/zjoybttx.html