如何在 React 中构建自动完成组件

介绍

Autocomplete 是一个功能,其中输入字段根据用户输入建议一个单词,这有助于改善应用程序中的用户体验,例如需要搜索的情况。

在本文中,您将研究如何在 React 中构建一个自动完成组件,您将使用固定的建议列表,事件约束,理解键盘代码,并运行状态管理。

前提条件

要完成本教程,您将需要以下内容:

要了解更多关于 React 的信息,请参阅 How To Code in React系列。

步骤 1 – 构建您的自动完成组件

自动完成组件是您将在自动完成功能中制作功能的地方。

创建一个Autocomplete.js文件,并导入 React 并实例化一个Autocomplete类:

 1[label Autocomplete.js]
 2import React, { Component, Fragment } from "react";
 3import './styles.css'
 4
 5class Autocomplete extends Component {
 6  constructor(props) {
 7    super(props);
 8    this.state = {
 9      activeSuggestion: 0,
10      filteredSuggestions: [],
11      showSuggestions: false,
12      userInput: ""
13    };
14  }

在您的状态中,activeSuggestion属性定义了选定的建议的索引。filteredSuggestions属性,设置为空数组,匹配了用户的输入。

随着您的类开始和状态设置,让我们看看在组件中应用的方法。

在您的Autocomplete.js文件中,定义一个onChange方法,并更新您的状态:

 1[label Autocomplete.js]
 2  onChange = e => {
 3    const { suggestions } = this.props;
 4    const userInput = e.currentTarget.value;
 5
 6    const filteredSuggestions = suggestions.filter(
 7      suggestion =>
 8        suggestion.toLowerCase().indexOf(userInput.toLowerCase()) > -1
 9    );
10
11    this.setState({
12      activeSuggestion: 0,
13      filteredSuggestions,
14      showSuggestions: true,
15      userInput: e.currentTarget.value
16    });
17  };

当用户更改输入值时,onChange方法会启动。每次更改时,该方法会过滤到建议列表并返回不包含用户输入的建议。过滤器完成后,.setState()方法会修改您的状态的userInput属性以包含一个值,设置显示建议字符,以允许建议显示,并在每个方法调用中重置activeSuggestion属性。

在您的Autocomplete.js文件中,声明一个onClick方法,并执行一个.setState()方法:

1[label Autocomplete.js]
2  onClick = e => {
3    this.setState({
4      activeSuggestion: 0,
5      filteredSuggestions: [],
6      showSuggestions: false,
7      userInput: e.currentTarget.innerText
8    });
9  };

.setState()方法会更新用户的输入并重置状态的属性。

在您的Autocomplete.js文件中,声明一个onKeyDown方法,并设置几个条件:

 1[label Autocomplete.js]
 2  onKeyDown = e => {
 3    const { activeSuggestion, filteredSuggestions } = this.state;
 4
 5    if (e.keyCode === 13) {
 6      this.setState({
 7        activeSuggestion: 0,
 8        showSuggestions: false,
 9        userInput: filteredSuggestions[activeSuggestion]
10      });
11    } else if (e.keyCode === 38) {
12      if (activeSuggestion === 0) {
13        return;
14      }
15      this.setState({ activeSuggestion: activeSuggestion - 1 });
16    }
17    // User pressed the down arrow, increment the index
18    else if (e.keyCode === 40) {
19      if (activeSuggestion - 1 === filteredSuggestions.length) {
20        return;
21      }
22      this.setState({ activeSuggestion: activeSuggestion + 1 });
23    }
24  };

一旦你将你的属性activeSuggestionfilteredSuggestion存储在一个解构的对象中,条件将检查用户按下的密钥是否匹配了密码。第一个条件将检查密码是否匹配了13,输入密钥,然后运行.setState()方法来更新userInput属性并关闭建议列表。如果用户按上箭头,按下密码38,条件将减少activeSuggestion属性的索引,如果索引为零,则不会返回任何东西。

随着您的方法现在完成,让我们导航到应用您的渲染生命周期方法。

Autocomplete.js文件中,设置一个render()语句,并定义你的方法和状态在一个解构对象中:

 1[label Autocomplete.js]
 2  render() {
 3    const {
 4      onChange,
 5      onClick,
 6      onKeyDown,
 7      state: {
 8        activeSuggestion,
 9        filteredSuggestions,
10        showSuggestions,
11        userInput
12      }
13    } = this;
14
15    let suggestionsListComponent;

变量SuggestionsListComponent没有定义值,因为您将在下面的条件中分配它们:

 1[label Autocomplete.js]
 2    if (showSuggestions && userInput) {
 3      if (filteredSuggestions.length) {
 4        suggestionsListComponent = (
 5          <ul class="suggestions">
 6            {filteredSuggestions.map((suggestion, index) => {
 7              let className;
 8
 9              // Flag the active suggestion with a class
10              if (index === activeSuggestion) {
11                className = "suggestion-active";
12              }
13              return (
14                <li className={className} key={suggestion} onClick={onClick}>
15                  {suggestion}
16                </li>
17              );
18            })}
19          </ul>
20        );
21      } else {
22        suggestionsListComponent = (
23          <div class="no-suggestions">
24            <em>No suggestions available.</em>
25          </div>
26        );
27      }
28    }

第一个条件将检查显示建议用户输入属性中的值是否存在,而下一个条件将检查过滤建议属性的长度。如果符合条件,建议ListComponent变量将自己分配通过过滤建议属性进行迭代的值,并标记一个具有类名称的活跃建议,如果索引匹配了活跃建议属性中的值。

如果用户不符合列出的条件,则render()生命周期方法将返回一个React``Fragment来应用输入字段并呼吁方法,而不添加额外的节点到文档对象模型:

 1[label Autocomplete.js]
 2    return (
 3      <Fragment>
 4        <input
 5          type="text"
 6          onChange={onChange}
 7          onKeyDown={onKeyDown}
 8          value={userInput}
 9        />
10        {suggestionsListComponent}
11      </Fragment>
12    );
13  }
14}
15
16export default Autocomplete;

现在你已经开发了自动完成组件,将文件导出并将其功能结合到另一个组件中。

步骤 2 – 加入您的 React 项目

App组件中,您将显示您的Autocomplete组件的功能。在您的index.js文件中,声明一个App组件并导入您的Autocomplete组件:

 1[label index.js]
 2import React from "react";
 3import Autocomplete from "./Autocomplete";
 4
 5function App() {
 6  return (
 7    <div>
 8      <h1>React Autocomplete Demo</h1>
 9      <h2>Start typing and experience the autocomplete wizardry!</h2>
10      <Autocomplete suggestions={"Oranges", "Apples", "Banana", "Kiwi", "Mango"]}/>
11    </div>
12  );
13}
14
15export default App

您的应用组件中的返回声明接受自动完成组件与固定的建议列表。

步骤 3 – 样式化您的自动完成组件

要完成您的自动完成组件,请使用 CSS 添加样式来定位和颜色您的应用程序和输入字段。

创建一个styles.css文件,并设置CSS规则来塑造你的自动完成组件:

 1[label styles.css]
 2body {
 3  font-family: sans-serif;
 4}
 5
 6input {
 7  border: 1px solid #999;
 8  padding: 0.5rem;
 9  width: 300px;
10}
11
12.no-suggestions {
13  color: #999;
14  padding: 0.5rem;
15}
16
17.suggestions {
18  border: 1px solid #999;
19  border-top-width: 0;
20  list-style: none;
21  margin-top: 0;
22  max-height: 143px;
23  overflow-y: auto;
24  padding-left: 0;
25  width: calc(300px + 1rem);
26}
27
28.suggestions li {
29  padding: 0.5rem;
30}
31
32.suggestion-active,
33.suggestions li:hover {
34  background-color: #008f68;
35  color: #fae042;
36  cursor: pointer;
37  font-weight: 700;
38}
39
40.suggestions li:not(:last-of-type) {
41  border-bottom: 1px solid #999;
42}

随着 CSS 规则的构建,将文件导入到您的Autocomplete.js文件中,以应用您的风格。

结论

React 提供了构建可在一个组件中可用的自动完成功能的措施,具有内置和自定义方法来与用户交互。

查看 Autocomplete 组件在 CodeSandbox中如何工作。

Published At
Categories with 技术
Tagged with
comments powered by Disqus