Day06 - Fetch、filter、正则表达式实现快速古诗匹配

Day06 - Fetch、filter、正则表达式实现快速古诗匹配

作者:liyuechun
简介:JavaScript30Wes Bos 推出的一个 30 天挑战。项目免费提供了 30 个视频教程、30 个挑战的起始文档和 30 个挑战解决方案源代码。目的是帮助人们用纯 JavaScript 来写东西,不借助框架和库,也不使用编译器和引用。现在你看到的是这系列指南的第 6 篇。完整中文版指南及视频教程在 从零到壹全栈部落

效果图

在输入框中搜索字或者某个词快速匹配含有这个字或者是词的诗句。

涉及特性

  • flex布局
  • nth-child奇偶匹配
  • linear-gradient颜色渐变
  • transform
  • Fetch
  • Array
    • filter()
    • map()
    • push()
    • join()
    • ...
  • JavaScript RegExp 对象
    • 字面量语法
    • 创建 RegExp 对象的语法
    • 修饰符ig
    • match()
    • replace()

实现步骤

  • UI布局
  • 通过Fetch下载数据
  • 数据处理并保存
  • 事件监听
  • 数据匹配操作
  • 新数据替换展示

布局篇

  • HTML代码
  <form class="search-form">
    <input type="text" class="search" placeholder="诗人名字,关键字">
    <ul class="suggestions">
      <li>输入词句,找一首诗</li>
      <li>输入词句,找一首诗</li>
      <li>输入词句,找一首诗</li>
      <li>输入词句,找一首诗</li>
      <li>输入词句,找一首诗</li>
    </ul>
  </form>
  • CSS代码
html {
  box-sizing: border-box;
  margin: 0px;
  background-color: rgb(145, 182, 195);
  font-family: 'Kaiti', 'SimHei', 'Hiragino Sans GB ', 'helvetica neue';
  font-size: 20px;
  font-weight: 200;
}

, :before, *:after {
  box-sizing: inherit;
}

body {
  display: flex;
  justify-content: center;
}

.search-form {
  max-width: 700px;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
}

input.search {
  padding: 20px;
  font-family: 'Kaiti', 'helvetica neue';
  margin: 0;
  border: 10px solid #f7f7f7;
  font-size: 40px;
  text-align: center;
  width: 120%;
  outline: 0;
  border-radius: 5px;
  position: relative;
  top: 10px;
  left: 10px;
  box-shadow: 0 0 5px rgba(0, 0, 0, 0.12), inset 0 0 2px rgba(0, 0, 0, 0.19);
}

.suggestions {
  margin: 0;
  padding: 0;
  position: relative;
  top: 7px;
  width: 100%;
}

.suggestions li {
  background: white;
  list-style: none;
  border-bottom: 1px solid #D8D8D8;
  box-shadow: 0 0 10px rgba(0, 0, 0, 0.14);
  margin: 0;
  padding: 20px;
  display: flex;
  flex-direction: column;
  /align-items: flex-start;/
}

span.title {
  margin-right: 20px;
  text-align: right;
  color: #7c8e94;
  margin-top: 5px;
}

span.hl {
  color: green;
}

/偶数匹配/
.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%);
}

通过Fetch下载数据解析并且保存

const endpoint = 'https://gist.githubusercontent.com/liyuechun/f00bb31fb8f46ee0a283a4d182f691b4/raw/3ea4b427917048cdc596b38b67b5ed664605b76d/TangPoetry.json';

const poetrys = [];
fetch(endpoint)
 .then(blob => {
   return blob.json();
 })
 .then(data => {
   poetrys.push(...data);
 });

具体数据请求过程见下图:

Fetch详细使用文档

blob.json()是将数据转换为json数据,data为then函数中转换完的数据,在这个案例中,data是一个数组。

poetrys.push(...data)这句代码中的push是往数组里面新增对象,而...data代表的是将这个data数组中的数据一一的存储到poetrys数组中。

事件监听

const search = document.querySelector('.search');
const suggestions = document.querySelector('.suggestions');

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

获取searchsuggestions'节点分别对changekeyup事件进行监听,当输入框中的内容发生变化或者键盘弹起时触发displayMatches函数更新数据。

数据匹配操作

  • RegExp使用基础

RegExp参考文档

  • 项目源码分析
function findMatches(wordToMatch, poetrys) {
 return poetrys.filter(poet => {
   // 正则找出匹配的诗句
   const regex = new RegExp(wordToMatch, 'gi');
   const author = poet.detail_author.join('');
   //           console.log(author);
   return poet.detail_text.match(regex) || poet.title.match(regex) || author.match(regex);
 });
}

function displayMatches() {
 const matches = findMatches(this.value, poetrys);
 const regex = new RegExp(this.value, 'gi');
 const html = matches.map(poet => {
   // 替换高亮的标签
   const text = poet.detail_text.replace(regex, `<span class="hl">${ this.value }</span>`);
   const title = poet.title.replace(regex, `<span class="hl">${ this.value }</span>`);
   const detail_author = poet.detail_author[0].replace(regex, `<span class="hl">${ this.value }</span>`);
   // 构造 HTML 值
   return `
 <li>
   <span class="poet">${ text }</span>
   <span class="title">${ title } - ${ detail_author }</span>
 </li>
`;
 }).join('');
 //     console.log(html);
 suggestions.innerHTML = html;
}
  • poetrys.filter会返回带搜索关键字的新数组。
  • const regex = new RegExp(this.value, 'gi'); 代表匹配规则。
  • g:执行全局匹配(查找所有匹配而非在找到第一个匹配后停止)。
  • i:执行对大小写不敏感的匹配。
  • 上面的这种写法等价于:"/this.value/gi"。
  • matches.map会返回一个按照新的规则处理完以后的新的数组。
  • title.replace(regex, "新字符串");表示将title字符串中满足 regex 规则的字符串替换成新字符串

源码下载

Github Source Code

春哥简介

简介: 资深讲师,全栈工程师;区块链、高可用架构技术爱好者。
个人博客:http://liyuechun.org
新浪微博:黎跃春-追时间的人
github:http://github.com/liyuechun

技术交流

  • 区块链技术交流QQ群:348924182
  • 「区块链部落」官方公众号

时间: 2024-10-07 19:38:25

Day06 - Fetch、filter、正则表达式实现快速古诗匹配的相关文章

c++-在做一个暴力破解密文的课设,如何快速地匹配文件中的单词?

问题描述 在做一个暴力破解密文的课设,如何快速地匹配文件中的单词? 最近在做一个课程设计,是关于暴力破解密文的.文件中大约有9000个单词,每个单词 占一行,如何快速地去匹配单词呢? 解决方案 先字典序排序.然后二分查找,这是我的想法,当然我觉得也可以用更高级的字符串匹配算法

积累比较常用的正则表达式(例如:匹配中文、匹配html)_正则表达式

正则表达式(Regular Expression,在代码中常简写为regex.regexp或RE)是计算机科学的一个概念.正则表达式使用单个字符串来描述.匹配一系列符合某个句法规则的字符串.在很多文本编辑器里,正则表达式通常被用来检索.替换那些符合某个模式的文本.许多程序设计语言都支持利用正则表达式进行字符串操作.在很多文本编辑器里,正则表达式通常被用来检索.替换那些符合某个模式的文本. 匹配中文字符的正则表达式: [u4e00-u9fa5]   评注:匹配中文还真是个头疼的事,有了这个表达式就

正则表达式教程之位置匹配详解

本文实例讲述了正则表达式教程之位置匹配.分享给大家供大家参考,具体如下: 注:在所有例子中正则表达式匹配结果包含在源文本中的[和]之间,有的例子会使用Java来实现,如果是java本身正则表达式的用法,会在相应的地方说明.所有java例子都在JDK1.6.0_13下测试通过. 一.问题引入 如果想匹配一段文本中的某个单词(暂不考虑多行模式,将在后面介绍),我们可能会像下面这样: 文本:Yesterday is history, tomorrow is a mystery, but today i

正则表达式教程之重复匹配详解

本文实例讲述了正则表达式教程之重复匹配.分享给大家供大家参考,具体如下: 注:在所有例子中正则表达式匹配结果包含在源文本中的[和]之间,有的例子会使用Java来实现,如果是java本身正则表达式的用法,会在相应的地方说明.所有java例子都在JDK1.6.0_13下测试通过. 一.有多少个匹配 前面几篇讲的都是匹配一个字符,但是一个字符或字符集合要匹配多次,应该怎么做呢?比如要匹配一个电子邮件地址,用之前说到的方法,可能有人会写出像\w@\w\.\w这样的正则表达式,但这个只能匹配到像a@b.c

正则表达式的3种匹配模式

正则表达式是处理字符串的常用工具.在C#中,我们一般使用Regex类来表示一个正则表达式.一般正则表达式引擎支持以下3种匹配模式:单行模式(Singleline).多行模式(Multiline)与忽略大小写(IgnoreCase). 1. 单行模式(Singleline)MSDN定义:更改点 (.) 的含义,使它与每一个字符匹配(而不是与除 \n 之外的每个字符匹配).使用单行模式的典型场景是获取网页源码中的信息.示例:我们使用WebBrowser控件,从http://www.xxx.com/1

Delphi中正则表达式语法(9) 临界匹配

//匹配右边 var reg: TPerlRegEx; begin reg := TPerlRegEx.Create(nil); reg.Subject := 'Delphi 6; Delphi 7; Delphi 2007; Delphi Net'; reg.RegEx := 'Delphi (?=2007)'; // ?= reg.Replacement := '◆'; reg.ReplaceAll; ShowMessage(reg.Subject); //返回: Delphi 6; Del

正则表达式教程之字符匹配

普通字符 普通字符由所有那些未显式指定为元字符的打印和非打印字符组成.这包括所有的大写和小写字母字符,所有数字,所有标点符号以及一些符号. 最简单的正则表达式是一个单独的普通字符,可以匹配所搜索字符串中的该字符本身.例如,单字符模式 'A' 可以匹配所搜索字符串中任何位置出现的字母 'A'.这里有一些单字符正则表达式模式的示例: /a/ /7/ /M/ 等价的 VBScript 单字符正则表达式为: "a" "7" "M" 可以将多个单字符组合在

正则表达式-请教php正则匹配时斜杠或冒号引起的问题

问题描述 请教php正则匹配时斜杠或冒号引起的问题 preg_match_all(""/>[w+="".*""s]+</"" $xml $pre); 我用正则去匹配类似下面的字符串: src1=""111"" src2=""bb"" src3=""ccc"" 匹配结果是:>src1=&quo

C#中正则表达式的3种匹配模式_C#教程

在C#中,我们一般使用Regex类来表示一个正则表达式.一般正则表达式引擎支持以下3种匹配模式:单行模式(Singleline).多行模式(Multiline)与忽略大小写(IgnoreCase). 1. 单行模式(Singleline) MSDN定义:更改点 (.) 的含义,使它与每一个字符匹配(而不是与除 \n 之外的每个字符匹配). 使用单行模式的典型场景是获取网页源码中的信息. 示例: 我们使用WebBrowser控件,从http://www.xxx.com/1.htm上获取了如下HTM