在React中从头开始创建一个搜索栏

1,839 阅读6分钟

搜索栏有助于筛选出必要的内容,为用户找到他们想要的结果。

你可能会想,有几个React库可以帮助你在几秒钟内建立一个搜索组件--为什么要浪费你的时间写一堆行来创建已经存在的东西?

或者,你可能想知道为什么在你的项目中使用一个库来实现一个搜索栏并不总是最好的主意。这里有一些关于它的想法。

下面是npm上一个流行包的详细报告。

A BundlePhobia report on the React Search Field package on npm

源于此。BundlePhobia

即使我们考虑该库的最小化版本,在项目中包含它也是相当大的。我们上面的代码大约是746字节,这比外面的任何库都要少很多!这就是我们的优势。

从头开始创建搜索栏的另一个好处是,它比库的可定制性要强得多。无论你在一个项目中使用多少库,从状态管理到组件,基础知识对一个开发者来说仍然相当重要。

在本教程中,我们将尝试复制一个搜索栏,跟踪输入栏的任何变化,并过滤出网站上存在的数据。更具体地说,我们将建立一个搜索栏,按标题过滤博客文章。

以下是我们在这篇文章中要介绍的内容。

  1. 设置起始文件
  2. 为搜索栏生成模拟数据
  3. 显示模拟数据
  4. 设计搜索栏的样式
  5. 实现搜索栏的功能

设置起始文件

继续前进,使用Create React App初始化一个新的React项目。

npx create-react-app search-bar-tutorial

前往根文件,删除所有不必要的文件。

Remove the unnecessary files from the root file

打开App.js 文件,清除原始JSX元素。

Remove the raw JSX elements from the App.js file

现在,创建一个输入字段供用户输入查询。

export default function App (){
  return {
    <div>
      <input placeholder="Enter Post Title"/>
    </div>
 }
}

为搜索栏生成模拟数据

接下来,让我们为搜索栏创建一些模拟数据来进行过滤。你可以创建你自己的模拟数据,或者简单地前往Mockaroo,轻松生成一些模拟数据。

继续并在模拟数据中输入你需要的字段。

Enter the fields you need for mock data

你创建的行数基本上应该与你在模拟数据中收到的对象数量相同,所以如果你把这个数字从默认的1000 ,效果会更好。确保你将文件类型设置为JSON。

Make sure you set the file type to JSON

点击预览,将你所有的模拟数据复制到你的代码编辑器中。

Copy the mock data into your code editor

做一个单独的文件--让我们称它为mock-data.json --并粘贴生成的数据。该JSON文件将看起来像这样。

The JSON file with the data

显示模拟数据

现在,在我们真正实现搜索栏的功能之前,让我们映射所有的数据,并在应用程序上显示它。

导入JSON数据,像这样。

import Data from "../mock-data.json"

由于模拟数据是一个数组,我们将使用JavaScript ES6Map 函数来循环浏览数组中的每个对象,并使用JSX来显示它。

{
  Data.map((post) => (
    <div key={post.id}>
      <p>{post.title}</p>
      <p>{post.author}</p>
    </div>
  ));
}

这将是它的结果。

The search field results page with no styling

搜索栏的样式

样式设计不是必须的,但没有任何CSS又有什么意思呢?如果你对造型演示很在行的话,请随意跳到下一节

让我们试着将每个元素居中,包括搜索栏。父元素的类名是app ,因此我们将以它为目标,使所有元素居中。

styles.css 文件中,以.app 类名为目标,应用flex 属性。

.app {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
}

Search field results with limited styling

这些帖子看起来还是很无聊。让我们为每个帖子制作一个卡片。在Map 函数中为JSX元素指定一个类名。

//App.js
{
  Data.map((post) => (
    <div className="box" key={post.id}>
      <p>{post.title}</p>
      <p>{post.author}</p>
    </div>
  ));
}

为了使每张卡片有区别,我们将使用边框属性并使边角变圆。

/* App.css */
.box {
  text-align: left;
  border: black ridge 1px;
  border-radius: 10px;
  margin: 3px;
  width: 20rem;
  padding-left: 10px;
}

Search field results with card styling

造型完成后,现在让我们回到本教程的重点--使搜索栏发挥作用

实现搜索栏的功能

现在是有趣的部分我们要跟踪用户在输入栏中输入的每一个变化。为此,我们使用useState Hook,并在输入栏有变化时设置状态。

import Data from "../mock-data.json";
import {useState} from "react";

export default function App (){
  const [query, setQuery] = useState("")
  return {
    <div>
      <input placeholder="Enter Post Title" onChange={event => setQuery(event.target.value)} />
    {
      Data.map((post, index) => {
        <div key={index}>
          <p>{post.title}</p>
          <p>{post.author}</p>
        </div>
      })
    }
    </div>
 }
}

完成这些后,我们要做的下一件事是看输入的查询是否与任何模拟数据相匹配。在我们的例子中,我们要看文章标题是否与输入的查询相匹配。这种方法将支持部分匹配和完全匹配。

在更基本的条件下,如果用户输入一个字母,该函数将返回所有将包括该字母的帖子标题。同样地,如果用户输入一个有效的单词,搜索函数将返回一个包含有该单词的帖子标题的数组。

Filter 方法在这种情况下是完美的。它返回一个满足指定条件的数组--这里的条件将是返回一个与用户输入的内容相匹配的新数组。

Data.filter(post => {
  if (query === "") {
    //if query is empty
    return post;
  } else if (post.title.toLowerCase().includes(query.toLowerCase())) {
    //returns filtered array
    return post;
  }
});

让我们把话说清楚。如果用户没有输入任何东西,我们可以说输入字段没有被使用,filter 函数将返回原始数组。

如果输入的查询与任何数据相匹配(在我们的例子中,是我们博客中的文章标题),那么它将返回一个新的数组,其中有与用户输入的查询相匹配的对象。为了避免由字母大写引起的任何错误,最好是将用户输入的查询和模拟数据中的post.title ,都转换成小写。这样一来,无论用户输入什么,即使都是小写字母,我们的过滤器仍然能够输出一个匹配的结果,如果找到一个的话。

为了显示过滤后的数据,我们只需将其与我们之前的Map 函数结合起来。

Flow behind the display of our filtered data

你的最终代码应该看起来像这样。

{
  Data.filter(post => {
    if (query === '') {
      return post;
    } else if (data.title.toLowerCase().includes(query.toLowerCase())) {
      return post;
    }
  }).map((post, index) => (
    <div className="box" key={index}>
      <p>{post.title}</p>
      <p>{post.author}</p>
    </div>
  ))
}

就这样了!做得很好。搜索栏应该已经准备好了。🚀

A final demo of the search field we built!

总结

现在你知道了如何在React中从头开始创建一个搜索栏,你可以根据项目要求进一步定制它。你可以让它调用某个API,也可以类似地显示数据。

此外,我们还遇到了一些JavaScript ES6函数,这些函数超级方便,可以用于其他应用,比如使用sort() 函数对过滤后的数据进行排序,按照你想要的顺序(日期、字母、时间等等)显示数据。

归根结底,从头开始创建的最大优势无疑是该组件与其他第三方软件包相比有多么灵活。你打算让你的搜索栏做什么?