【问题标题】:how to create React search filter for search multiple object key values如何创建 React 搜索过滤器以搜索多个对象键值
【发布时间】:2019-01-18 23:28:54
【问题描述】:

我想为我的数据数组创建一个搜索过滤器。它有多个像这样的对象和键,

[
    {
        "fname": "Jayne",
        "lname": "Washington",
        "email": "jaynewashington@exposa.com",
        "gender": "female"
    },
    {
        "fname": "Peterson",
        "lname": "Dalton",
        "email": "petersondalton@exposa.com",
        "gender": "male"
    },
    {
        "fname": "Velazquez",
        "lname": "Calderon",
        "email": "velazquezcalderon@exposa.com",
        "gender": "male"
    },
    {
        "fname": "Norman",
        "lname": "Reed",
        "email": "normanreed@exposa.com",
        "gender": "male"
    }
]

我想在这个数组的任何地方进行搜索过滤器搜索。 例如:当我输入输入框时,我想搜索对象内的任何位置。比如 fname,lname,email,gender

我该怎么做?请帮帮我

如果我想限制只搜索名字和姓氏,该怎么做?

【问题讨论】:

    标签: javascript reactjs loops


    【解决方案1】:

    您可以在组件状态中保留一个值 filter,并使用它来查看它是否作为子字符串包含在任何数组元素属性中。

    示例

    class App extends React.Component {
      state = {
        filter: "",
        data: [
          {
            fname: "Jayne",
            lname: "Washington",
            email: "jaynewashington@exposa.com",
            gender: "female"
          },
          {
            fname: "Peterson",
            lname: "Dalton",
            email: "petersondalton@exposa.com",
            gender: "male"
          },
          {
            fname: "Velazquez",
            lname: "Calderon",
            email: "velazquezcalderon@exposa.com",
            gender: "male"
          },
          {
            fname: "Norman",
            lname: "Reed",
            email: "normanreed@exposa.com",
            gender: "male"
          }
        ]
      };
    
      handleChange = event => {
        this.setState({ filter: event.target.value });
      };
    
      render() {
        const { filter, data } = this.state;
        const lowercasedFilter = filter.toLowerCase();
        const filteredData = data.filter(item => {
          return Object.keys(item).some(key =>
            item[key].toLowerCase().includes(lowercasedFilter)
          );
        });
    
        return (
          <div>
            <input value={filter} onChange={this.handleChange} />
            {filteredData.map(item => (
              <div key={item.email}>
                <div>
                  {item.fname} {item.lname} - {item.gender} - {item.email}
                </div>
              </div>
            ))}
          </div>
        );
      }
    }
    
    ReactDOM.render(<App />, document.getElementById("root"));
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
    
    <div id="root"></div>

    【讨论】:

    • 搜索男性也会匹配女性。为此需要使用正则表达式。 ^1
    • @BhojendraNepal 不需要正则表达式。如果您只想从字符串的开头进行匹配,您可以使用 startsWith,但 OP 并没有说明这一点,所以我假设需要 includes 类型搜索。
    • @BhojendraNepal 不一定。 female 包含male,如果这不是 OP 想要的,他可以在评论中告诉我。
    • @Tholle 哦,我忘了一个。如果搜索字段为空x[key].toLowerCase().includes(searchText.toLowerCase()) || !searchText,我更改了这一行
    • 如果数据/JSON 具有非字符串值,如布尔值或浮点数,则此代码将中断。像这样将对象转换为字符串:item[key].toString().toLowerCase().includes(lowercasedFilter)
    【解决方案2】:

    搜索多个对象键值的过滤器并突出显示搜索词

    实现了两个函数 - highlighterfilterHandler

    filterHandler 函数根据给定的输入过滤数据,然后将过滤后的数据发送到荧光笔函数进行高亮显示。

    highlighter 函数接受两个参数 obj 和 input,它以字符串形式返回可突出显示的 HTML 代码。

    class App extends React.Component {
      state = {
        input: "",
        fData: [{
            fname: "Jayne",
            lname: "Washington",
            email: "jaynewashington@exposa.com",
            gender: "female"
          },
          {
            fname: "Peterson",
            lname: "Dalton",
            email: "petersondalton@exposa.com",
            gender: "male"
          },
          {
            fname: "Velazquez",
            lname: "Calderon",
            email: "velazquezcalderon@exposa.com",
            gender: "male"
          },
          {
            fname: "Norman",
            lname: "Reed",
            email: "normanreed@exposa.com",
            gender: "male"
          }
        ],
        data: [{
            fname: "Jayne",
            lname: "Washington",
            email: "jaynewashington@exposa.com",
            gender: "female"
          },
          {
            fname: "Peterson",
            lname: "Dalton",
            email: "petersondalton@exposa.com",
            gender: "male"
          },
          {
            fname: "Velazquez",
            lname: "Calderon",
            email: "velazquezcalderon@exposa.com",
            gender: "male"
          },
          {
            fname: "Norman",
            lname: "Reed",
            email: "normanreed@exposa.com",
            gender: "male"
          }
        ]
      };
    
    
      handleChange = event => {
        this.setState({
          input: event.target.value
        }, this.filterHandler);
      };
    
      highlighter = (obj, lowercasedInput) => {
        let rawObj = obj.replace(`<span class='highlight'>`, '').replace(`</span>`, '');
    
        if (rawObj.indexOf(lowercasedInput) != -1) {
          const startIndex = rawObj.indexOf(lowercasedInput);
          const endIndex = startIndex - 1 + lowercasedInput.length;
    
          if (startIndex != 0) {
            return rawObj.slice(0, startIndex) + `<span class='highlight'>${lowercasedInput}</span>` + rawObj.slice(endIndex + 1, rawObj.length);
          } else {
            return rawObj.slice(0, startIndex) + `<span class='highlight'>${lowercasedInput}</span>` + rawObj.slice(endIndex + 1, rawObj.length);
          }
        } else {
          return rawObj
        }
      }
    
    
      filterHandler = () => {
        const {
          input,
          data
        } = this.state;
        const lowercasedInput = input.toLowerCase();
    
        const filteredData = data.filter(item => {
          return Object.keys(item).some(key =>
            item[key].toLowerCase().includes(lowercasedInput)
          );
        });
    
        let highlightFD = [];
        filteredData.map((values, index) => {
          highlightFD.push({ ...values
          });
        })
    
    
        if (lowercasedInput.trim().length > 0) {
          highlightFD.map((val, index) => {
            for (let key in val) {
              highlightFD[index][key] = this.highlighter(val[key].toLowerCase(), lowercasedInput);
            }
          });
        }
    
        this.setState({
          fData: highlightFD
        });
    
      }
    
      render() {
        const {
          input,
          fData
        } = this.state;
    
    
    
        return ( <
            div >
            <
            input value = {
              input
            }
            onChange = {
              this.handleChange
            }
            /> {
            fData.map(item => ( <div key ={item.email} className = "results" >
             <div dangerouslySetInnerHTML = {{__html: item.fname}}/>&nbsp;|&nbsp; 
             <div dangerouslySetInnerHTML = {{__html: item.lname}}/>&nbsp;|&nbsp; 
             <div dangerouslySetInnerHTML = {{__html: item.gender}}/>&nbsp;|&nbsp; 
              <div dangerouslySetInnerHTML = {{__html: item.email}}/>  
            </div >
            ))
          } </div>
      );
    }
    }
    
    ReactDOM.render( < App / > , document.getElementById("root"));
    .results {
      display: flex
    }
    
    span {
      background-color:black;
      color:white;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
    
    <div id="root"></div>

    注意: dangerouslySetInnerHTML 是 React 在浏览器 DOM 中使用 innerHTML 的替代品。一般来说,从代码中设置 HTML 是有风险的,因为很容易在不经意间将您的用户暴露给跨站点脚本 (XSS) 攻击。

    阅读更多:https://reactjs.org/docs/dom-elements.html#dangerouslysetinnerhtml

    使用正则表达式:

    class App extends React.Component {
      state = {
        input: "",
        fData: [{
            fname: "Jayne",
            lname: "Washington",
            email: "jaynewashington@exposa.com",
            gender: "female"
          },
          {
            fname: "Peterson",
            lname: "Dalton",
            email: "petersondalton@exposa.com",
            gender: "male"
          },
          {
            fname: "Velazquez",
            lname: "Calderon",
            email: "velazquezcalderon@exposa.com",
            gender: "male"
          },
          {
            fname: "Norman",
            lname: "Reed",
            email: "normanreed@exposa.com",
            gender: "male"
          }
        ],
        data: [{
            fname: "Jayne",
            lname: "Washington",
            email: "jaynewashington@exposa.com",
            gender: "female"
          },
          {
            fname: "Peterson",
            lname: "Dalton",
            email: "petersondalton@exposa.com",
            gender: "male"
          },
          {
            fname: "Velazquez",
            lname: "Calderon",
            email: "velazquezcalderon@exposa.com",
            gender: "male"
          },
          {
            fname: "Norman",
            lname: "Reed",
            email: "normanreed@exposa.com",
            gender: "male"
          }
        ]
      };
    
    
      handleChange = event => {
        this.setState({
          input: event.target.value
        }, this.filterHandler);
      };
    
      highlighter = (obj, lowercasedInput) => {
        let rawObj = obj.replace(`<span class='highlight'>`, '').replace(`</span>`, '');
    
        if (rawObj.indexOf(lowercasedInput) != -1) {
          const startIndex = rawObj.indexOf(lowercasedInput);
          const endIndex = startIndex - 1 + lowercasedInput.length;
    
          if (startIndex != 0) {
            return rawObj.slice(0, startIndex) + `<span class='highlight'>${lowercasedInput}</span>` + rawObj.slice(endIndex + 1, rawObj.length);
          } else {
            return rawObj.slice(0, startIndex) + `<span class='highlight'>${lowercasedInput}</span>` + rawObj.slice(endIndex + 1, rawObj.length);
          }
        } else {
          return rawObj
        }
      }
    
    
      filterHandler = () => {
        const {
          input,
          data
        } = this.state;
        const lowercasedInput = input.toLowerCase();
    
        const filteredData = data.filter(item => {
          return Object.keys(item).some(key =>{
             const regex= new RegExp(`^${lowercasedInput.trim()}`,'i');
                return regex.test(item[key].toLowerCase()) ;
             }
          );
        });
    
        let highlightFD = [];
        filteredData.map((values, index) => {
          highlightFD.push({ ...values
          });
        })
    
    
        if (lowercasedInput.trim().length > 0) {
          highlightFD.map((val, index) => {
            for (let key in val) {
              highlightFD[index][key] = this.highlighter(val[key].toLowerCase(), lowercasedInput);
            }
          });
        }
    
        this.setState({
          fData: highlightFD
        });
    
      }
    
      render() {
        const {
          input,
          fData
        } = this.state;
    
    
    
        return ( <
            div >
            <
            input value = {
              input
            }
            onChange = {
              this.handleChange
            }
            /> {
            fData.map(item => ( <div key ={item.email} className = "results" >
             <div dangerouslySetInnerHTML = {{__html: item.fname}}/>&nbsp;|&nbsp; 
             <div dangerouslySetInnerHTML = {{__html: item.lname}}/>&nbsp;|&nbsp; 
             <div dangerouslySetInnerHTML = {{__html: item.gender}}/>&nbsp;|&nbsp; 
              <div dangerouslySetInnerHTML = {{__html: item.email}}/>  
            </div >
            ))
          } </div>
      );
    }
    }
    
    ReactDOM.render( < App / > , document.getElementById("root"));
    .results {
      display: flex
    }
    
    span {
      background-color:black;
      color:white;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
    
    <div id="root"></div>

    【讨论】:

      【解决方案3】:
      fData.filter((person) => {
        return object
          .value(person)
          .join('')
          .toLowerCase()
          .include(searchinput.toLowerCase())
      })
      

      这里的searchinput 是您在输入中输入的值,由状态控制。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-02-09
        • 2019-07-12
        • 2020-11-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-07-10
        相关资源
        最近更新 更多