使用Fuse.js将动态搜索添加到React应用

移动开发 Android
Fuse.js是一个轻量级的搜索引擎,可以在用户的浏览器中的客户端运行。让我们看看如何使用它来轻松地为React应用添加搜索功能。

Fuse.js是一个轻量级的搜索引擎,可以在用户的浏览器中的客户端运行。让我们看看如何使用它来轻松地为React应用添加搜索功能。

[[402547]]

何时使用Fuse.js

搜索功能对很多类型的网站都很有用,可以让用户高效地找到他们想要的东西。但为什么我们会专门选择使用Fuse.js呢?

为搜索提供动力的选择有很多,最简单的可能是使用现有的数据库。例如,Postgres有一个全文搜索功能。MySQL也有,Redis也有RediSearch模块。

还有一些专门的搜索引擎,其中Elasticsearch和Solr是最受欢迎的。这些搜索引擎需要更多的设置,但它们拥有你的用例可能需要的高级功能。

最后,你可以使用Algolia或Swiftype等搜索即服务平台。这些服务运行自己的搜索基础架构。你只需通过API提供数据、配置和查询。

但是,您可能不需要这些解决方案所暴露的能力,这可能需要大量的工作来实现,更不用说成本了。如果没有太多的数据需要搜索,Fuse.js需要最小的设置,并且可以提供比您自己可能想到的更好的搜索体验。

至于多少数据对Fuse.js来说是过多的,考虑到Fuse.js需要访问整个数据集,所以你需要在客户端全部加载。如果数据集的大小是100MB,那就超出了发送给客户端的合理范围。但如果它只有几千字节,它可能是Fuse.js的一个很好的候选者。

构建一个Fuse.js + React演示应用程序

让我们做一个基本的React应用,使用Fuse.js让用户搜索狗的品种。你可以在这里查看最终的结果,源代码可以在GitHub上找到。

我们将从设置一些脚手架开始。从一个新的Node.js项目开始,我们将安装React和Fuse.js:

  1. npm install --save react react-dom fuse.js 
  2. //or 
  3. yarn add react react-dom fuse.js 

我们还将安装Parcel作为开发依赖项:

  1. npm install --save-dev parcel@2.0.0-beta.1 
  2. //or 
  3. yarn add --dev parcel@2.0.0-beta.1 

我们将在 package.json 启动脚本中使用它来编译应用程序:

  1. {   
  2.   "scripts": { 
  3.     "start": "parcel serve ./index.html --open" 
  4.   } 

接下来,我们将创建一个barebones index.html,其中包含一个空的 div 供React渲染,以及一个 noscript 消息,以避免在用户禁用JavaScript时出现空白页面。

  1. <!DOCTYPE html> 
  2. <html lang="en"> 
  3.   <body> 
  4.     <div id="app"></div> 
  5.     <noscript> 
  6.       <p>Please enable JavaScript to view this page.</p> 
  7.     </noscript> 
  8.     <script src="./index.js"></script> 
  9.   </body> 
  10. </html> 

我们将使我们的 index.js 简单的开始。我们将渲染一个有搜索查询输入的表单,尽管我们还不会实际处理搜索。

  1. import React, { useState } from "react"; 
  2. import ReactDom from "react-dom"; 
  3.  
  4. function Search() { 
  5.   return ( 
  6.     <form> 
  7.       <label htmlFor="query">Search for a dog breed:</label> 
  8.       <input type="search" id="query" /> 
  9.       <button>Search</button> 
  10.     </form> 
  11.   ); 
  12.  
  13. ReactDom.render(<Search />, document.getElementById("app")); 

此时,如果你运行 npm run start 或 yarn run start,Parcel应该会在浏览器中打开网站,你应该会看到这个表单。

实施搜索

现在开始实施搜索,我们将从显示搜索结果的组件开始。我们需要处理三种情况:

  • 用户尚未执行搜索时
  • 没有查询结果时(因为我们不希望用户认为某些问题)
  • 什么时候有结果显示

我们将在ordered list中显示所有结果。

  1. function SearchResults(props) { 
  2.   if (!props.results) { 
  3.     return null; 
  4.   } 
  5.  
  6.   if (!props.results.length) { 
  7.     return <p>There are no results for your query.</p>
  8.   } 
  9.  
  10.   return ( 
  11.     <ol> 
  12.       {props.results.map((result) => ( 
  13.         <li key={result}>{result}</li> 
  14.       ))} 
  15.     </ol> 
  16.   ); 

我们也来编写自己的搜索函数。稍后,我们将能够将我们的简单方法的结果与Fuse.js的结果进行比较。

我们的方法很简单:我们将遍历犬种数组(来自这个JSON列表),并返回包含整个搜索查询的所有犬种。我们还会让所有东西都小写,这样搜索就不区分大小写了。

  1. const dogs = [ 
  2.   "Affenpinscher", 
  3.   "Afghan Hound", 
  4.   "Aidi", 
  5.   "Airedale Terrier", 
  6.   "Akbash Dog", 
  7.   "Akita", 
  8.   // More breeds.. 
  9. ]; 
  10.  
  11. function searchWithBasicApproach(query) { 
  12.   if (!query) { 
  13.     return []; 
  14.   } 
  15.  
  16.   return dogs.filter((dog) => dog.toLowerCase().includes(query.toLowerCase())); 

接下来,让我们将所有内容链接在一起,方法是从表单提交中获取搜索查询,然后执行搜索并显示结果。

  1. function Search() { 
  2.   const [searchResults, setSearchResults] = useState(null); 
  3.  
  4.   return ( 
  5.     <> 
  6.       <form 
  7.         onSubmit={(event) => { 
  8.           event.preventDefault(); 
  9.           const query = event.target.elements.query.value; 
  10.           const results = searchWithBasicApproach(query); 
  11.           setSearchResults(results); 
  12.         }} 
  13.       > 
  14.         <label htmlFor="query">Search for a dog breed:</label> 
  15.         <input type="search" id="query" /> 
  16.         <button>Search</button> 
  17.       </form> 
  18.  
  19.       <SearchResults results={searchResults} /> 
  20.     </> 
  21.   ); 

添加Fuse.js

使用Fuse.js很简单,我们需要导入它,让它使用 new Fuse() 对数据进行索引,然后使用索引的搜索功能。搜索会返回一些元数据,所以我们将只提取实际的项目进行展示。

  1. import Fuse from "fuse.js"; 
  2.  
  3. const fuse = new Fuse(dogs); 
  4.  
  5. function searchWithFuse(query) { 
  6.   if (!query) { 
  7.     return []; 
  8.   } 
  9.  
  10.   return fuse.search(query).map((result) => result.item); 

元数据包括一个 refIndex 整数,让我们可以回溯到原始数据集中的相应项目。如果我们用 new Fuse(dogs, {includeScore: true}) 初始化索引,我们也会得到匹配分数:一个介于0和1之间的值,其中0是完全匹配。那么“Husky”的搜索结果就会像这样:

  1.   { 
  2.     item: "Siberian Husky", 
  3.     refIndex: 386, 
  4.     score: 0.18224241177399383 
  5.   } 

我们将在 Search 组件的表单中添加一个复选框,让用户选择是否使用Fuse.js而不是基本的搜索函数。

  1. <form 
  2.   onSubmit={(event) => { 
  3.     event.preventDefault(); 
  4.     const query = event.target.elements.query.value; 
  5.     const useFuse = event.target.elements.fuse.checked; 
  6.     setSearchResults( 
  7.       useFuse ? searchWithFuse(query) : searchWithBasicApproach(query) 
  8.     ); 
  9.   }} 
  10. > 
  11.   <label htmlFor="query">Search for a dog breed: </label> 
  12.   <input type="search" id="query" /> 
  13.   <input type="checkbox" name="fuse" /> 
  14.   <label htmlFor="fuse"> Use Fuse.js</label> 
  15.   <button>Search</button> 
  16. </form> 

现在我们可以用Fuse.js进行搜索了!我们可以使用复选框来比较使用它和不使用它。

最大的区别在于Fuse.js可以容忍错别字(通过近似字符串匹配),而我们的基本搜索则需要精确匹配。如果我们把“retriever”拼错为“retreiver”,请查看基本搜索结果。

以下是针对同一查询更有用的Fuse.js结果:

搜索多个字段

如果我们关心多个字段,我们的搜索可能会更复杂。例如,想象一下,我们想通过品种和原产国来搜索。Fuse.js支持这种用例。当我们创建索引时,我们可以指定要索引的对象键。

  1. const dogs = [ 
  2.   {breed: "Affenpinscher", origin: "Germany"}, 
  3.   {breed: "Afghan Hound", origin: "Afghanistan"}, 
  4.   // More breeds.. 
  5. ]; 
  6.  
  7. const fuse = new Fuse(dogs, {keys: ["breed", "origin"]}); 

现在,Fuse.js将同时搜索 breed 和 origin 字段。

总结

有时候,我们不想花费资源去建立一个完整的Elasticsearch实例。当我们有简单的需求时,Fuse.js可以提供相应的简单解决方案。而正如我们所看到的,将它与React一起使用也是很简单的。

即使我们需要更高级的功能,Fuse.js也允许给不同的字段赋予不同的权重,添加 AND 和 OR 逻辑,调整模糊匹配逻辑等等。当你下次需要在应用中添加搜索功能时,可以考虑使用它。

责任编辑:赵宁宁 来源: 今日头条
相关推荐

2022-03-14 08:54:04

NetlifyHTMLReact

2011-11-15 14:52:39

Mac OSWindows域

2021-05-26 14:39:27

FedoraLinux企业域

2019-04-17 14:32:39

加密文件Windows 10搜索结果

2011-07-18 10:32:39

域控制器

2017-05-09 14:00:00

SambaWinbindUbuntu

2018-10-15 09:30:11

ChromeYouTubeLinux

2020-02-11 12:54:34

Linux日志文件消息

2011-07-27 17:45:29

iPhone 模拟器 图片

2023-05-24 10:04:36

微软ChatGPT人工智能

2020-11-17 11:18:31

Docker

2021-06-15 05:45:56

Linkerd annotations网络技术

2022-06-10 09:29:42

苹果删除原生系统

2019-03-06 15:02:56

应用程序Windows 10 右键单击菜单

2019-11-07 09:20:36

Windows 10联系人Outlook

2023-06-08 15:17:13

iOSChatGPT

2023-11-14 22:16:36

2010-08-31 15:14:55

DB2域账户

2015-12-01 09:23:14

Windows 10开始菜单网站

2021-01-07 15:54:19

谷歌iOS应用苹果
点赞
收藏

51CTO技术栈公众号