antd3.X Mentions重名搜索bug

bug描述

项目需求,我们用的antd3.26.15。 用到Mentions组件的时候,value我们使用的是名字 (name) 字段,这时候就会出现 重名 情况。当我需要 @ 某人的时候,我模糊搜索的时候,再次搜索名称就会一直出现。如图。第一个名字不应该出现,这个名字也是 重名 的名称。
第一个不应该出现

思路

排查问题之后知道是option里面的value太片面了(value又是选择是填充的值,这个值又不能重复)OnSelect里面的参数就是这个value又不能改,于是我们又加了个字段actualValue。加了个字段那肯定就是要去看源码了。看看怎么改源码。(这个还是前辈做出来的,我顺着他的思路理了一遍,哈哈哈,白嫖思路)
首先想到的肯定去看antd的源码。看了源码其实也狠模糊从何做起。说说我个人的思考路线,首先思路里面提到加了个actualValue,那我们需要看Option里面是什么东西,这时候就能定位到getOption,看到就返回了children。意思就是返回了全部东西了。
在这里插入图片描述
这里看到了RcMentions组件,看到了咱们用的是rc-mentions。咱们又去github上找。继续思路,上面咱们提到children,所以我们直接在这里索引children,发现好像也就是整理了一下(这里我理解其实就是我们能传递actualName的关键)。这个时候我又想到了OnSelect方法,那就又索引这个方法呗。其实这个时候我们就能定位到关键方法selectOption 了,一些解释放在代码注释里面了。

import RcMentions from 'rc-mentions';

在这里插入图片描述

  public selectOption = (option: OptionProps) => {
    const { value, measureLocation, measurePrefix } = this.state;
    const { split, onSelect } = this.props;
	// 这里就是我们传过去的value,那么是不是可以在这里加actualName
    const { value: mentionValue = '' } = option;
    // const { value: mentionValue = '', actualValue } = option;
    const { text, selectionLocation } = replaceWithMeasure(value, {
      measureLocation,
      targetText: mentionValue, // 这里就是复制,那么我们也可以把actualvalue赋值给他
      // targetText: actualValue ?? mentionValue,
      prefix: measurePrefix,
      selectionStart: this.textarea!.selectionStart,
      split: split!,
    });
    this.triggerChange(text);
    this.stopMeasure(() => {
      // We need restore the selection position
      setInputSelection(this.textarea!, selectionLocation);
    });
	// 这里又把我们的option传递回去了,就是Onselct的参数
    if (onSelect) {
      onSelect(option, measurePrefix);
    }
  };

于是乎

问题就解决了我们写一个MyMention组件继承Mention组件,MyRcMention继承RcMention就可以了。

// MyMention
import classNames from 'classnames';
import { Mentions } from "antd";
import MyRCMentions from "./MyRCMentions";
import omit from 'omit.js';

export default class MyMentions extends Mentions {

    constructor(props) {
        super(props);
    }
    renderMentions = ({ getPrefixCls, renderEmpty }) => {
        const { focused } = this.state;
        const { prefixCls: customizePrefixCls, className, disabled, ...restProps } = this.props;
        const prefixCls = getPrefixCls('mentions', customizePrefixCls);
        const mentionsProps = omit(restProps, ['loading']);

        const mergedClassName = classNames(className, {
            [`${prefixCls}-disabled`]: disabled,
            [`${prefixCls}-focused`]: focused,
        });

        return (
            <MyRCMentions
                prefixCls={prefixCls}
                notFoundContent={this.getNotFoundContent(renderEmpty)}
                className={mergedClassName}
                disabled={disabled}
                {...mentionsProps}
                filterOption={this.getFilterOption()}
                onFocus={this.onFocus}
                onBlur={this.onBlur}
                ref={this.saveMentions}
            >
                {this.getOptions()}
            </MyRCMentions>
        );
    };

    render() {
        return super.render();
    }
}

// MyRcMention
import RcMentions from 'rc-mentions';
import { replaceWithMeasure, setInputSelection } from 'rc-mentions/lib/util';

export default class MyRCMentions extends RcMentions {

    constructor(props) {
        super(props);
    }

    selectOption = (option) => {
        const { value, measureLocation, measurePrefix } = this.state;
        const { split, onSelect } = this.props;
        const { value: mentionValue = '', actualValue } = option;
        const { text, selectionLocation } = replaceWithMeasure(value, {
            measureLocation,
            targetText: actualValue ?? mentionValue,
            prefix: measurePrefix,
            selectionStart: this.textarea.selectionStart,
            split: split,
        });
        this.triggerChange(text);
        this.stopMeasure(() => {
            // We need restore the selection position
            setInputSelection(this.textarea, selectionLocation);
        });

        if (onSelect) {
            onSelect(option, measurePrefix);
        }
    };

    render() {
        return super.render()
    }
}

最后

看似很简单,其实我们做了好久,刚开始我都没往源码这方面想,请教了前辈,他跟我一起解决这个bug,才做出来了。学到了很多。这个问题感觉应该很小众了,antd都更新了那么多版本了,应该是解决了。发出来也只是让我自己有一个思路,如果真有解决不了的bug,看看源码,从源码入手,想想能不能解决。
还有就是我其实是写Vue的,如果源码解释的有问题,可以帮忙提出来,谢谢大哥们

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值