关于前端:使用Fusejs将动态搜索添加到React应用

54次阅读

共计 4238 个字符,预计需要花费 11 分钟才能阅读完成。

Fuse.js 是一个轻量级的搜索引擎,能够在用户的浏览器中的客户端运行。让咱们看看如何应用它来轻松地为 React 利用增加搜寻性能。

何时应用 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:

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

咱们还将装置 Parcel 作为开发依赖项:

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

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

{  
  "scripts": {"start": "parcel serve ./index.html --open"}
}

接下来,咱们将创立一个 barebones index.html,其中蕴含一个空的 div 供 React 渲染,以及一个 noscript 音讯,以防止在用户禁用 JavaScript 时呈现空白页面。

<!DOCTYPE html>
<html lang="en">
  <body>
    <div id="app"></div>
    <noscript>
      <p>Please enable JavaScript to view this page.</p>
    </noscript>
    <script src="./index.js"></script>
  </body>
</html>

咱们将使咱们的 index.js 简略的开始。咱们将渲染一个有搜寻查问输出的表单,只管咱们还不会理论解决搜寻。

import React, {useState} from "react";
import ReactDom from "react-dom";

function Search() {
  return (
    <form>
      <label htmlFor="query">Search for a dog breed:</label>
      <input type="search" id="query" />
      <button>Search</button>
    </form>
  );
}

ReactDom.render(<Search />, document.getElementById("app"));

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

施行搜寻

当初开始施行搜寻,咱们将从显示搜寻后果的组件开始。咱们须要解决三种状况:

  1. 用户尚未执行搜寻时
  2. 没有查问后果时(因为咱们不心愿用户认为某些问题)
  3. 什么时候有结果显示

咱们将在 ordered list 中显示所有后果。

function SearchResults(props) {if (!props.results) {return null;}

  if (!props.results.length) {return <p>There are no results for your query.</p>;}

  return (
    <ol>
      {props.results.map((result) => (<li key={result}>{result}</li>
      ))}
    </ol>
  );
}

咱们也来编写本人的搜寻函数。稍后,咱们将可能将咱们的简略办法的后果与 Fuse.js 的后果进行比拟。

咱们的办法很简略:咱们将遍历犬种数组 (来自这个 JSON 列表),并返回蕴含整个搜寻查问的所有犬种。咱们还会让所有货色都小写,这样搜寻就不辨别大小写了。

const dogs = [
  "Affenpinscher",
  "Afghan Hound",
  "Aidi",
  "Airedale Terrier",
  "Akbash Dog",
  "Akita",
  // More breeds..
];

function searchWithBasicApproach(query) {if (!query) {return [];
  }

  return dogs.filter((dog) => dog.toLowerCase().includes(query.toLowerCase()));
}

接下来,让咱们将所有内容链接在一起,办法是从表单提交中获取搜寻查问,而后执行搜寻并显示后果。

function Search() {const [searchResults, setSearchResults] = useState(null);

  return (
    <>
      <form
        onSubmit={(event) => {event.preventDefault();
          const query = event.target.elements.query.value;
          const results = searchWithBasicApproach(query);
          setSearchResults(results);
        }}
      >
        <label htmlFor="query">Search for a dog breed:</label>
        <input type="search" id="query" />
        <button>Search</button>
      </form>

      <SearchResults results={searchResults} />
    </>
  );
}

增加 Fuse.js

应用 Fuse.js 很简略,咱们须要导入它,让它应用 new Fuse() 对数据进行索引,而后应用索引的搜寻性能。搜寻会返回一些元数据,所以咱们将只提取理论的我的项目进行展现。

import Fuse from "fuse.js";

const fuse = new Fuse(dogs);

function searchWithFuse(query) {if (!query) {return [];
  }

  return fuse.search(query).map((result) => result.item);
}

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

[
  {
    item: "Siberian Husky",
    refIndex: 386,
    score: 0.18224241177399383
  }
]

咱们将在 Search 组件的表单中增加一个复选框,让用户抉择是否应用 Fuse.js 而不是根本的搜寻函数。

<form
  onSubmit={(event) => {event.preventDefault();
    const query = event.target.elements.query.value;
    const useFuse = event.target.elements.fuse.checked;
    setSearchResults(useFuse ? searchWithFuse(query) : searchWithBasicApproach(query)
    );
  }}
>
  <label htmlFor="query">Search for a dog breed: </label>
  <input type="search" id="query" />
  <input type="checkbox" name="fuse" />
  <label htmlFor="fuse"> Use Fuse.js</label>
  <button>Search</button>
</form>

当初咱们能够用 Fuse.js 进行搜寻了!咱们能够应用复选框来比拟应用它和不应用它。

最大的区别在于 Fuse.js 能够容忍错别字(通过近似字符串匹配),而咱们的根本搜寻则须要准确匹配。如果咱们把“retriever”拼错为“retreiver”,请查看根本搜寻后果。

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

搜寻多个字段

如果咱们关怀多个字段,咱们的搜寻可能会更简单。例如,设想一下,咱们想通过种类和原产国来搜寻。Fuse.js 反对这种用例。当咱们创立索引时,咱们能够指定要索引的对象键。

const dogs = [{breed: "Affenpinscher", origin: "Germany"},
  {breed: "Afghan Hound", origin: "Afghanistan"},
  // More breeds..
];

const fuse = new Fuse(dogs, {keys: ["breed", "origin"]});

当初,Fuse.js 将同时搜寻 breedorigin 字段。

总结

有时候,咱们不想破费资源去建设一个残缺的 Elasticsearch 实例。当咱们有简略的需要时,Fuse.js 能够提供相应的简略解决方案。而正如咱们所看到的,将它与 React 一起应用也是很简略的。

即便咱们须要更高级的性能,Fuse.js 也容许给不同的字段赋予不同的权重,增加 ANDOR 逻辑,调整含糊匹配逻辑等等。当你下次须要在利用中增加搜寻性能时,能够思考应用它。

正文完
 0