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的,如果源码解释的有问题,可以帮忙提出来,谢谢大哥们

《完整神武新章服务端源码》是一个与游戏开发相关的资源,主要使用Delphi编程语言编写的。 Delphi是一款强大的面向对象的集成开发环境(IDE),尤其在Windows平台上的应用开发方面享有很高的声誉。 本资源包含的服务端源码是网络游戏《神武新章》的核心部分,它负责处理游戏服务器的逻辑、网络通信、数据库交互以及玩家间的游戏行为同步等关键功能。 1. **Delphi编程基础**:Delphi采用Object Pascal语言,它是一种高效且简洁的面向对象语言。 源码中可能包含类定义、继承、多态性、接口等面向对象设计概念。 理解Delphi的基本语法和面向对象特性是分析和修改源码的基础。 2. **网络编程**:服务端源码中必然涉及网络通信模块,如TCP/IP协议栈的使用,用于建立客户端和服务端之间的连接。 源码地址: https://pan.quark.cn/s/4014bf1007ee 这部分可能涉及到套接字编程,包括监听、接受连接、发送和接收数据等操作。 3. **并发处理**:由于服务器需要同时处理多个客户端的请求,因此并发处理是服务端源码中的重要部分。 Delphi提供了线程和异步编程机制,如TThread类和IO完成端口等技术,用于实现高效的并发控制。 4. **数据库交互**:游戏服务端通常需要与数据库进行交互,存储和检索玩家信息、游戏数据等。 可能使用到ADO(ActiveX Data Objects)或DirectSQL等数据库访问组件,掌握SQL语言和数据库事务处理是必要的。 5. **游戏逻辑**:这部分源码包含了游戏规则的实现,比如角色移动、战斗计算、任务系统等。 这些逻辑可能分布在多个类和函数中,通过事件驱动或消息传递机制进行协调。 6. **加密与安全**:...
<think>我们参考了用户提供的多个引用,这些引用主要围绕在React项目中使用Ant Design 3.x版本,结合less和webpack来实现主题切换。以下将逐步说明实现方法: ### 1. 安装必要的依赖 首先确保项目中已安装`antd@3.x`(如3.6.5),并安装以下开发依赖: - `babel-plugin-import`:用于按需加载组件样式 - `less`:编译less文件(注意版本,引用[2]建议less保持在2.8以下以避免错误) - `less-loader`:webpack处理less文件的loader(版本需兼容) - `css-loader`和`style-loader`:处理CSS - `less-vars-to-js`(可选):用于将less变量转换为JS对象(引用[2]中提到) 执行命令: ```bash npm install antd@3.x --save npm install babel-plugin-import less less-loader@5.0.0 css-loader style-loader --save-dev # 如果使用less-vars-to-js,则安装 npm install less-vars-to-js --save-dev ``` ### 2. 配置.babelrc 在项目根目录下创建或修改`.babelrc`文件,配置`babel-plugin-import`插件以实现按需加载: ```json { "plugins": [ ["import", { "libraryName": "antd", "style": "css" }] ] } ``` 注意:引用[2]中提到,使用该插件后,antd的样式会按需加载,但这里我们实现主题切换需要修改为加载less文件(因为主题变量在less中),所以将`"style": "css"`改为`"style": true`(即加载less): ```json { "plugins": [ ["import", { "libraryName": "antd", "style": true }] // 加载less ] } ``` ### 3. 配置webpack 修改webpack配置文件(通常为`webpack.config.js`),添加less文件的处理规则,并配置`less-loader`的`modifyVars`选项来覆盖antd的默认变量。 #### 关键步骤: - 添加less文件的loader规则(参考引用[3]和[4]) - 在`less-loader`的选项中,通过`modifyVars`传入要修改的主题变量(引用[1]) 示例配置: ```javascript // webpack.config.js module.exports = { // ...其他配置 module: { rules: [ // ...其他规则 { test: /\.less$/, use: [ { loader: &#39;style-loader&#39; }, { loader: &#39;css-loader&#39; }, { loader: &#39;less-loader&#39;, options: { lessOptions: { // 注意:less-loader高版本(如6.x以上)需要lessOptions,低版本(5.x)则直接配置 modifyVars: { &#39;primary-color&#39;: &#39;#1DA57A&#39;, // 主色 &#39;link-color&#39;: &#39;#1DA57A&#39;, // 链接色 &#39;border-radius-base&#39;: &#39;2px&#39; // 圆角 }, javascriptEnabled: true, // 允许内联JavaScript(antd需要) } } } ] } ] } }; ``` #### 注意: - 根据引用[1]和[2],`modifyVars`是一个对象,键是要覆盖的antd主题变量名,值是新值。 - 引用[1]提到,在webpack配置中通过`modifyVars`修改主题变量,每次构建时更换对应色值即可实现主题切换。 - 如果使用`less-loader@5`,则不需要`lessOptions`这一层级(引用[1]注释中提到),直接写在`options`里即可。 ### 4. 动态切换主题(可选) 如果需要在运行时动态切换主题,可以考虑以下方案: - 将主题变量提取到一个单独的less文件中(如`theme.less`),然后通过`less.modifyVars`动态修改变量(但此方法需要浏览器环境支持less.js,不常用)。 - 另一种方法是构建多个主题CSS文件,在运行时切换CSS文件(引用[2]未提及,但引用[1]提到每次构建时更换变量)。 由于antd 3.x的主题切换主要是在构建时通过webpack配置完成,因此动态切换需要更复杂的方案(如多主题打包)。通常做法是: 1. 准备多个主题变量文件(如`theme1.js`,`theme2.js`)。 2. 在构建时根据环境变量或脚本动态修改webpack配置中的`modifyVars`。 3. 生成多份CSS,在页面中切换链接。 ### 5. 注意事项 - **字体大小调整**:引用[2]提到,antd 3.6.5默认字体为14px,若需要调整,可修改`@font-size-base`变量。 - **less版本兼容性**:引用[2]强调less版本需保持在2.8以下以避免错误。 - **按需加载**:确保babel插件配置正确,否则会导致样式重复加载或缺失。 ### 总结 使用antd 3.x、less和webpack实现主题切换的关键在于: 1. 安装正确版本的依赖(尤其是less和less-loader)。 2. 配置babel-plugin-import实现样式按需加载(加载less源文件)。 3. 在webpack的less-loader配置中使用modifyVars覆盖antd的less变量。 这样,在构建时修改`modifyVars`中的变量值即可实现主题切换[^1][^2][^3][^4]。 §§相关问题§§ 1. 如何动态切换antd主题(运行时切换)? 2. antd 4.x的主题切换方法与3.x有何不同? 3. 如何自定义antd组件的样式变量? </think>基于提供的引用内容,以下是使用 Ant Design 3.x + Less + Webpack 实现主题切换的完整方案: ### 核心实现步骤 1. **安装必要依赖** ```bash npm install antd@3.x --save npm install babel-plugin-import less less-loader@5.0.0 css-loader style-loader --save-dev npm install less-vars-to-js --save-dev # 用于转换LESS变量 ``` 2. **配置 `.babelrc`** ```json { "plugins": [ ["import", { "libraryName": "antd", "style": true // 关键配置:启用LESS加载 }] ] } ``` 3. **修改 Webpack 配置(webpack.config.js)** ```javascript { test: /\.less$/, use: [ { loader: &#39;style-loader&#39; }, { loader: &#39;css-loader&#39; }, { loader: &#39;less-loader&#39;, options: { lessOptions: { // less-loader@5 需此层级 modifyVars: { // 主题覆盖变量 &#39;primary-color&#39;: &#39;#1DA57A&#39;, // 主色调 &#39;link-color&#39;: &#39;#1DA57A&#39;, // 链接色 &#39;border-radius-base&#39;: &#39;2px&#39;, // 圆角 &#39;font-size-base&#39;: &#39;14px&#39; // 字体大小 }, javascriptEnabled: true // 必须启用 } } } ] } ``` ### 关键配置说明 1. **`modifyVars` 对象** 通过覆盖 Ant Design 的 [Less 变量](https://github.com/ant-design/ant-design/blob/master/components/style/themes/default.less) 实现主题定制: ```javascript modifyVars: { &#39;@primary-color&#39;: &#39;#1890ff&#39;, // 全局主色 &#39;@link-color&#39;: &#39;#1890ff&#39;, // 链接色 &#39;@success-color&#39;: &#39;#52c41a&#39;, // 成功色 &#39;@border-radius-base&#39;: &#39;4px&#39;, // 组件/浮层圆角 &#39;@font-size-base&#39;: &#39;16px&#39; // 主字号 } ``` 2. **版本兼容要点** - 使用 `less-loader@5.x`(高版本需调整配置) - Less 保持在 `2.7.x` 版本(引用[2]建议) - Ant Design 3.x 与 4.x+ 的主题机制不同 ### 动态切换方案(高级) 1. **创建主题配置文件** ```js // themes.js export default { light: { &#39;@primary-color&#39;: &#39;#1890ff&#39;, &#39;@menu-dark-bg&#39;: &#39;#ffffff&#39; }, dark: { &#39;@primary-color&#39;: &#39;#722ed1&#39;, &#39;@menu-dark-bg&#39;: &#39;#001529&#39; } } ``` 2. **动态修改 Webpack 配置** ```javascript // 在构建脚本中动态设置 const theme = process.env.THEME || &#39;light&#39;; const themeVars = require(`./src/themes/${theme}`); // webpack配置中 modifyVars: themeVars ``` 3. **通过 npm 脚本切换** ```json "scripts": { "build:light": "THEME=light webpack", "build:dark": "THEME=dark webpack" } ``` ### 注意事项 1. 必须设置 `javascriptEnabled: true`(Ant Design 样式依赖) 2. 按需加载需配合 `babel-plugin-import` 的 `style: true` 配置 3. 修改配置后需重启开发服务器 4. 组件样式不支持动态切换(需重新构建)[^1][^2][^4] > 此方案通过编译时覆盖LESS变量实现主题切换,适合需要固定主题的场景。如需运行时动态切换,需配合CSS变量或多主题文件加载方案[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值