You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Draft.js自定义Decorator无效果问题排查与解决求助

问题:Draft.js Decorator无法替换输入的链接为指定Google链接

我尝试为Draft.js制作第一个Decorator,按照文档实现了LinkDecorator、Utils工具类,并在MyEditor中使用,但用户输入链接时,页面上只显示输入的链接文本,没有替换成指向Google的链接。即使修改了LinkDecorator.js中matchFunction里的Utils.regexMatch参数为Utils.regexMatch(regex,contentBlock,callback),问题依然存在。

现有代码实现

1. LinkDecorator.js

import React from 'react';
import Utils from './Utils';
const Link= (props) => {
 console.log(props);
 return ( <a href="http://google.com">GOOGLE</a> );
}
const matchFunction = (contentBlock, callback, contentState) => {
 const regex=/(https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|www\.[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9]\.[^\s]{2,}|www\.[a-zA-Z0-9]\.[^\s]{2,})/
 Utils.regexMatch(regex,contentBlock,callback);
}
export default { 'strategy': matchFunction, 'component': Link };

2. Utils.js

export default {
 'regexMatch': (regex, contentBlock, callback)=>{
 const text = contentBlock.getText();
 let matchArr = regex.exec(text);
 let start;
 console.log("Block Content", text);
 while (matchArr !== null) {
 start = matchArr.index;
 callback(start, start + matchArr[0].length);
 matchArr = regex.exec(text);
 }
 },
}

3. MyEditor.js

import React, { Component } from 'react';
import { EditorState, CompositeDecorator } from 'draft-js';
import { Editor } from 'react-draft-wysiwyg';
import 'react-draft-wysiwyg/dist/react-draft-wysiwyg.css';
import Link from './LinkDecorator';
class MyEditor extends Component {
 constructor(props){
 super(props);
 const compositeDecorator = new CompositeDecorator([Link]);
 this.state = {
 compositeDecorator,
 editorState: EditorState.createEmpty(compositeDecorator),
 };
 }
 onEditorStateChange: Function = (editorState) => {
 this.setState({editorState,});
 };
 render() {
 const { editorState } = this.state;
 return ( <Editor editorState={editorState} wrapperClassName="demo-wrapper" editorClassName="demo-editor" onEditorStateChange={this.onEditorStateChange} /> );
 }
}
export default MyEditor;

问题原因分析

1. 正则表达式缺少全局匹配标志

你的正则表达式没有添加g(全局匹配)标志,这会导致regex.exec(text)每次调用都从字符串开头开始匹配,永远返回第一个匹配结果,直接陷入无限循环——既无法遍历文本中所有链接,也不会正常触发Decorator的渲染逻辑。

2. 匹配循环逻辑失效

由于正则没有全局标志,regex.exec(text)不会自动推进匹配位置,循环无法终止,Decorator的strategy函数根本无法完成执行,自然不会调用callback来标记需要装饰的文本范围。


修复步骤

步骤1:给正则添加全局匹配标志

修改LinkDecorator.js中的正则定义,加上g标志:

const regex = /(https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|www\.[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9]\.[^\s]{2,}|www\.[a-zA-Z0-9]\.[^\s]{2,})/g;

步骤2:验证匹配循环正常执行

添加g标志后,regex.exec(text)会自动更新lastIndex,每次调用都会从上次匹配的结束位置开始查找,循环可以正常遍历所有匹配项,正确触发callback标记装饰范围。

步骤3:优化Link组件(可选)

如果你想显示用户输入的原链接文本而不是固定的"GOOGLE",可以修改Link组件使用Draft.js传递的children参数(即匹配到的原文本):

const Link = (props) => {
  console.log(props);
  return <a href="http://google.com">{props.children}</a>;
};

步骤4:确认Editor配置有效性

react-draft-wysiwyg的Editor组件会正确继承editorState中的CompositeDecorator,你当前的代码已经在初始化时传入了Decorator,后续onEditorStateChange更新状态时也会自动保留,无需额外配置。


修复后的完整LinkDecorator.js

import React from 'react';
import Utils from './Utils';

const Link = (props) => {
  console.log(props);
  // 可选择显示原链接文本或固定文本
  return <a href="http://google.com">{props.children}</a>;
};

const matchFunction = (contentBlock, callback, contentState) => {
  // 添加全局匹配标志g
  const regex = /(https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|www\.[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9]\.[^\s]{2,}|www\.[a-zA-Z0-9]\.[^\s]{2,})/g;
  Utils.regexMatch(regex, contentBlock, callback);
};

export default { strategy: matchFunction, component: Link };

额外提示

如果还是没生效,可以打开浏览器控制台检查是否有报错(比如之前正则无g标志导致的栈溢出),同时确认Utils.js中的regexMatch参数传递正确(你修改后的参数是对的,strategy函数的第二个参数就是callback)。

内容的提问来源于stack exchange,提问作者Dimitrios Desyllas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 07:09:40