一个无限层级树形选择器的动态搜索高亮function

需求

如下图的一个带搜索功能的树形选择器,搜索的时候隐藏掉没有关联的节点,同时,如果子节点中有命中的,则不隐藏。

示例图,来自Antd

思路

  1. 首先,这个树形选择器的层级并不能确定,这里考虑用一个方法递归调用来实现。
  2. 递归实现的思路应该从最后一个子节点思考,并且父节点在子节点命中了搜索词的时候也要显示。

代码实现

最后实现的代码就如下,觉得还是比较有趣的,也算是写了很久无聊的业务代码写点逻辑换个心情吧。

铺垫一下,data的数据结构:

treeData: PropTypes.arrayOf(
  PropTypes.shape({
    id: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
    name: PropTypes.string,
    subTrees: PropTypes.arrayOf(
      PropTypes.shape({
        id: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
        name: PropTypes.string,
        iconClassName: PropTypes.string,
      })
    ),
  })
),

递归function代码如下:

  renderTreeNodes = data => {
    const { searchValue, isSearchFilter } = this.props;

    const returnData = [];
    for (const item of data) {
      const { name } = item;

      let title = this.highlightSearchValue(name, searchValue);
      if (item.iconClassName) {
        title = (
          <span>
            <i className={`${ICON_FONT} ${item.iconClassName}`} />
            {title}
          </span>
        );
      }
      if (item.subTrees) {
        const subTreeNodes = this.renderTreeNodes(item.subTrees);
        if (
          (isSearchFilter && subTreeNodes.length > 0) ||
          (!isSearchFilter || name.indexOf(searchValue) > -1)
        ) {
          // if on searchFilter mode, push the parent node when child nodes exist
          returnData.push(
            <TreeNode key={item.id} title={title}>
              {subTreeNodes}
            </TreeNode>
          );
        }
      } else if (!isSearchFilter || name.indexOf(searchValue) > -1) {
        // if on searchFilter mode, push the last child node only when the node is match the search value
        // otherwise, push the node anyway
        returnData.push(<TreeNode key={item.id} title={title} />);
      }
    }
    return returnData;
  };

文本怎么高亮?实现如下:

  highlightSearchValue = (name, searchValue) => {
    if (!searchValue) {
      return <span>{name}</span>;
    }

    const index = name.indexOf(searchValue);
    const beforeStr = name.substr(0, index);
    const afterStr = name.substr(index + searchValue.length);
    return index > -1 ? (
      <span>
        {beforeStr}
        <span className={cx('highlight-search-value')}>{searchValue}</span>
        {afterStr}
      </span>
    ) : (
      <span>{name}</span>
    );
  };
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容