一個(gè)無限層級(jí)樹形選擇器的動(dòng)態(tài)搜索高亮function

需求

如下圖的一個(gè)帶搜索功能的樹形選擇器,搜索的時(shí)候隱藏掉沒有關(guān)聯(lián)的節(jié)點(diǎn),同時(shí),如果子節(jié)點(diǎn)中有命中的,則不隱藏。

示例圖,來自Antd

思路

  1. 首先,這個(gè)樹形選擇器的層級(jí)并不能確定,這里考慮用一個(gè)方法遞歸調(diào)用來實(shí)現(xiàn)。
  2. 遞歸實(shí)現(xiàn)的思路應(yīng)該從最后一個(gè)子節(jié)點(diǎn)思考,并且父節(jié)點(diǎn)在子節(jié)點(diǎn)命中了搜索詞的時(shí)候也要顯示。

代碼實(shí)現(xiàn)

最后實(shí)現(xiàn)的代碼就如下,覺得還是比較有趣的,也算是寫了很久無聊的業(yè)務(wù)代碼寫點(diǎn)邏輯換個(gè)心情吧。

鋪墊一下,data的數(shù)據(jù)結(jié)構(gòu):

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;
  };

文本怎么高亮?實(shí)現(xiàn)如下:

  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>
    );
  };
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容