RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 946571
Accepted
Владислав
Владислав
Asked:2020-02-19 16:27:39 +0000 UTC2020-02-19 16:27:39 +0000 UTC 2020-02-19 16:27:39 +0000 UTC

如何通过映射更改 React 中的组件类

  • 772

我学习 React,阅读文档,教程。我决定尝试将 JSP 翻译成 React 的一个单独的前端。我从一个小组件开始,这就是自动搜索,原理是,我们输入一个单词,它会给出选项。

几乎一切都解决了,但我不知道如何通过上下键滚动列表,我不知道如何传递上面的属性并告诉一个或另一个 li 将类更改为选中。

我尝试使用 map(item, key),但是如何将属性传递给这个项目,例如?

这是我的代码,我也想请你看看我是否把它清理干净了,或者如果有评论立即解析它们,我将不胜感激:)

import React, { Component } from "react";
import "./App.css";

class ProductRow extends React.Component {
  constructor(props) {
    super(props);
    this.handlerrOnMouseOver = this.handlerrOnMouseOver.bind(this);
    this.handlerrOnMouseOut = this.handlerrOnMouseOut.bind(this);
    this.handlerrOnMouseDown = this.handlerrOnMouseDown.bind(this);
    this.state = {
      class: ""
    };
  }

  handlerrOnMouseOver() {
    this.setState({
      class: "selected"
    });
  }

  handlerrOnMouseOut() {
    this.setState({
      class: ""
    });
  }

  handlerrOnMouseDown() {
    this.props.callback(this.props.product.station);
  }

  render() {
    const product = this.props.product;
    return (
      <li
        className={this.state.class}
        onMouseOver={this.handlerrOnMouseOver}
        onMouseOut={this.handlerrOnMouseOut}
      >
        <a href="javascript:void(0);" onMouseDown={this.handlerrOnMouseDown}>
          {product.station}
        </a>
      </li>
    );
  }
}

class ProductTable extends React.Component {
  render() {
    const filterText = this.props.filterText;
    const rows = [];
    if (filterText !== "") {
      this.props.products.map((product, key) => {
        if (
          product.station.toLowerCase().indexOf(filterText.toLowerCase()) ===
            -1 ||
          rows.length === 20
        ) {
          return;
        } else {
          rows.push(
            <ProductRow
              product={product}
              key={key}
              callback={this.props.callback}
            />
          );
        }
      });
    }

    var style = {
      width: "100%",
      fontSize: 14
    };

    if (rows.length > 0) {
      return (
        <div className="sf_suggestion">
          <ul tabIndex="-1" style={style}>
            {rows}
          </ul>
        </div>
      );
    } else {
      return <div />;
    }
  }
}

class SearchBar extends React.Component {
  constructor(props) {
    super(props);
    this.handlerFilterTextChange = this.handlerFilterTextChange.bind(this);
    this.handlerOnKeyUp = this.handlerOnKeyUp.bind(this);
    this.handlerOnBlur = this.handlerOnBlur.bind(this);
    this.changeValue = this.changeValue.bind(this);
    this.handlerOnFocus = this.handlerOnFocus.bind(this);
    this.state = {
      visible: true,
      filterText: "",
      key: ""
    };
  }

  handlerFilterTextChange(e) {
    e.preventDefault();
    this.setState({ filterText: e.target.value });
  }

  handlerOnKeyUp() {
    var key = window.event.keyCode;
    if (key === 38 || key === 40 || key === 13) {
      this.setState({ key: key });
    }
    if (key === 27) {
      this.setState({ visible: false });
    }
  }

  changeValue(e) {
    this.setState({ filterText: e });
    this.handlerOnBlur();
  }

  handlerOnBlur() {
    this.setState({ visible: false });
    this.setState({ key: "" });
  }

  handlerOnFocus() {
    if (!this.state.visible) {
      this.setState({ visible: true });
    }
  }

  render() {
    return (
      <p className="inp">
        <label>
          <input
            type="text"
            placeholder="&nbsp;"
            value={this.state.filterText}
            onChange={this.handlerFilterTextChange}
            onFocus={this.handlerOnFocus}
            onKeyUp={this.handlerOnKeyUp}
            onBlur={this.handlerOnBlur}
          />
          <span className="label">{this.props.name}</span>
          <span className="border" />
          {this.state.visible && (
            <ProductTable
              products={this.props.products}
              filterText={this.state.filterText}
              keyUp={this.state.key}
              callback={this.changeValue}
            />
          )}
        </label>
      </p>
    );
  }
}

class App extends Component {
  render() {
    return (
      <table>
        <tbody>
          <td>
            <SearchBar products={this.props.products} name={"Имя"} />
          </td>
        </tbody>
      </table>
    );
  }
}

export default App;
reactjs
  • 1 1 个回答
  • 10 Views

1 个回答

  • Voted
  1. Best Answer
    Alexandr Tovmach
    2020-02-19T18:14:51Z2020-02-19T18:14:51Z

    带有注释的重构版本:

    import React, { Component } from "react";
    import "./App.css";
    
    class ProductRow extends React.Component {
      constructor(props) {
        super(props);
        this.handlerrOnMouseOver = this.handlerrOnMouseOver.bind(this);
        this.handlerrOnMouseOut = this.handlerrOnMouseOut.bind(this);
        this.handlerrOnMouseDown = this.handlerrOnMouseDown.bind(this);
        this.state = {
          className: "" // class очень плохое название, потому что является зарезервированным названием ЯП. Используйте className или подобное
        };
      }
    
      handlerrOnMouseOver() {
        this.setState({
          className: "selected"
        });
      }
    
      handlerrOnMouseOut() {
        this.setState({
          className: ""
        });
      }
    
      handlerrOnMouseDown() {
        /**
         * нужно всегда проверять пришли ли пропсы, потому что если нет, то вывалит ошибку что не может получить callback из undefined
         * деструктуризация делает код более читабельным
         */
        const { callback, product } = this.props;
    
        callback && callback(product && product.station);
      }
    
      render() {
        // бессмысленная запись, которая ничего не дает
        // const product = this.props.product;
    
        /**
         * используйте деструктуризацию
         */
        const { product } = this.props;
        const { className } = this.state;
    
        return (
          <li
            className={className}
            onMouseOver={this.handlerrOnMouseOver}
            onMouseOut={this.handlerrOnMouseOut}
          >
            <a href="javascript:void(0);" onMouseDown={this.handlerrOnMouseDown}>
              {product.station}
            </a>
          </li>
        );
      }
    }
    
    class ProductTable extends React.Component {
      render() {
        /**
         * используйте деструктуризацию
         */
        const { filterText, products, callback } = this.props;
        // бессмысленная запись, которая ничего не дает
        // const filterText = this.props.filterText;
    
        // лучше присваивать CSS-класс, чем инлайновый стиль
        var style = {
          width: "100%",
          fontSize: 14
        };
    
        /**
         * судя по коду, нет обязательной привязки к пустой строке, поэтому простой проверки будет достаточно
         */
        return (
          filterText && (
            <div className="sf_suggestion">
              <ul tabIndex="-1" style={style}>
                {products
                  .filter(
                    (product, i) =>
                      product.station
                        .toLowerCase()
                        // includes() более новый и удобный метод
                        .includes(filterText.toLowerCase()) && (
                        <ProductRow product={product} key={i} callback={callback} />
                      )
                  )
                  .slice(0, 20)}
              </ul>
            </div>
          )
        );
      }
    }
    
    class SearchBar extends React.Component {
      constructor(props) {
        super(props);
        this.handlerFilterTextChange = this.handlerFilterTextChange.bind(this);
        this.handlerOnKeyUp = this.handlerOnKeyUp.bind(this);
        this.handlerOnBlur = this.handlerOnBlur.bind(this);
        this.changeValue = this.changeValue.bind(this);
        this.handlerOnFocus = this.handlerOnFocus.bind(this);
        this.state = {
          visible: true,
          filterText: "",
          key: ""
        };
      }
    
      handlerFilterTextChange(e) {
        e.preventDefault();
        this.setState({ filterText: e.target.value });
      }
    
      handlerOnKeyUp() {
        var key = window.event.keyCode;
        if (key === 38 || key === 40 || key === 13) {
          this.setState({ key: key });
        }
        if (key === 27) {
          this.setState({ visible: false });
        }
      }
    
      changeValue(e) {
        this.setState({ filterText: e });
        this.handlerOnBlur();
      }
    
      handlerOnBlur() {
        // обновляйте весь стейт за раз
        this.setState({
          visible: false,
          key: ""
        });
      }
    
      handlerOnFocus() {
        if (!this.state.visible) {
          this.setState({ visible: true });
        }
      }
    
      render() {
        return (
          <p className="inp">
            <label>
              <input
                type="text"
                placeholder="&nbsp;"
                value={this.state.filterText}
                onChange={this.handlerFilterTextChange}
                onFocus={this.handlerOnFocus}
                onKeyUp={this.handlerOnKeyUp}
                onBlur={this.handlerOnBlur}
              />
              <span className="label">{this.props.name}</span>
              <span className="border" />
              {this.state.visible && (
                <ProductTable
                  products={this.props.products}
                  filterText={this.state.filterText}
                  keyUp={this.state.key}
                  callback={this.changeValue}
                />
              )}
            </label>
          </p>
        );
      }
    }
    
    class App extends Component {
      render() {
        return (
          <table>
            <tbody>
              <td>
                <SearchBar products={this.props.products} name={"Имя"} />
              </td>
            </tbody>
          </table>
        );
      }
    }
    
    export default App;
    

    我的版本(我不确定为什么在 JS 中而不是在 CSS 中处理悬停时的颜色变化,但我没有改变它,而是在代码中做到了):

    const mockData = [
      {
        station: "first",
      },
      {
        station: "second",
      },
      {
        station: "third",
      },
    ]
    
    class Search extends React.Component {
    
      constructor(props) {
        super(props);
    
        this.state = {
          filteredItems: props.items || [],
          selectedItem: null
        };
      }
    
      onFilterTextChanged = (event) => {
        event.preventDefault();
        const { items } = this.props;
        this.setState({
          filteredItems: items.filter(el => el.station.toLowerCase().includes(event.target.value.toLowerCase()))
        });
      }
    
      onKeyUp = ({ keyCode }) => {
        const { selectedItem, filteredItems } = this.state;
        if (keyCode === 40) {
          if (selectedItem === null) {
            this.setState({ selectedItem: 0 });
          } else if (selectedItem < filteredItems.length - 1) {
            this.setState({ selectedItem: selectedItem + 1 });
          }
        }
        if (keyCode === 38) {
          if (selectedItem > 0) {
            this.setState({ selectedItem: selectedItem - 1 });
          }
        }
      }
    
      onMouseOver = (index) => {
        this.setState({
          selectedItem: index
        });
      }
    
      onMouseOut = () => {
        this.setState({
          selectedItem: null
        });
      }
    
      render() {
        const { selectedItem, filteredItems } = this.state;
    
        return (
          <div>
            <input
              type="text"
              placeholder="Enter station to filter..."
              onChange={this.onFilterTextChanged}
              onKeyUp={this.onKeyUp}
            />
            <table>
              <tbody>
                {
                  filteredItems.map((item, i) => (
                    <tr
                      key={`item-${i}`}
                      className={selectedItem === i? `selected` : ``}
                      onMouseOver={() => this.onMouseOver(i)}
                      onMouseOut={() => this.onMouseOut()}
                    >
                      <td>{item.station}</td>
                    </tr>
                  ))
                }
              </tbody>
            </table>
          </div>
        );
      }
    }
    
    class App extends React.Component {
      render() {
        return (
          <Search items={mockData} />
        )
      }
    }
    
    ReactDOM.render(<App />, document.getElementById('root'));
    .selected {
      background-color: lavender;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
    
    <div id="root"></div>

    • 2

相关问题

  • map()中的模态窗口反应js

  • ReactDOM.render() 出错

  • 道具不显示

  • 如何更改可观察数组中的值?

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    根据浏览器窗口的大小调整背景图案的大小

    • 2 个回答
  • Marko Smith

    理解for循环的执行逻辑

    • 1 个回答
  • Marko Smith

    复制动态数组时出错(C++)

    • 1 个回答
  • Marko Smith

    Or and If,elif,else 构造[重复]

    • 1 个回答
  • Marko Smith

    如何构建支持 x64 的 APK

    • 1 个回答
  • Marko Smith

    如何使按钮的输入宽度?

    • 2 个回答
  • Marko Smith

    如何显示对象变量的名称?

    • 3 个回答
  • Marko Smith

    如何循环一个函数?

    • 1 个回答
  • Marko Smith

    LOWORD 宏有什么作用?

    • 2 个回答
  • Marko Smith

    从字符串的开头删除直到并包括一个字符

    • 2 个回答
  • Martin Hope
    Alexandr_TT 2020年新年大赛! 2020-12-20 18:20:21 +0000 UTC
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5