javascript - 由于装饰器过多,随着内容的增加,Draft js Editor 变慢了

标签 javascript reactjs draftjs

所以我的 draft-js 编辑器变得非常慢(hacky)我插入的内容越多(在大约 20 个装饰器替换之后)。我猜这种行为是由于装饰器使用正则表达式检查整个编辑器内容,并在每次状态更改时用表情符号组件替换匹配项。我还为正则表达式找到的每个匹配项创建实体,我通过使用编辑器状态作为 Prop 装饰组件来做到这一点。有没有办法让它更快? 这是我的装饰器:

       {
            strategy: emojiStrategy,
            component: decorateComponentWithProps(RenderEmoji, {
                getEditorState: this.getEditorState,
                setEditorState: this.onChange
            })
        }

这是我的表情符号策略:

function emojiRegexF(regex, contentBlock, callback, contentState) {
    const text = contentBlock.getText();
    let matchArr, start;

    while ((matchArr = regex.exec(text)) !== null) {
        start = matchArr.index;

        callback(start, start + matchArr[0].length);
    }
}
function emojiStrategy(contentBlock, callback, contentState) {
    emojiRegexF(EMOJI_REGEX, contentBlock, callback, contentState);
}

这是我的 RenderEmoji 组件:

const RenderEmoji = props => {
    const contentBlock = props.children[0].props.block;
    const emojiKey = contentBlock.getEntityAt(props.children[0].props.start);
    const emojiShortName = props.decoratedText;
    if (!emojiKey) {
        setEntity(props, emojiShortName);
    }

    return (
        <Emoji emoji={emojiShortName} set="emojione" size={24}>
            {props.children}
        </Emoji>
    );
};

这是设置匹配实体的 setEntity 函数:

function setEntity(props, emojiShortName) {
    const editorState = props.getEditorState();
    const contentstate = editorState.getCurrentContent();
    const contentStateWithEntity = contentstate.createEntity(
        "emoji",
        "IMMUTABLE",
        {
            emojiUnicode: emojiShortName
        }
    );

    const entityKey = contentStateWithEntity.getLastCreatedEntityKey();
    const oldSelectionState = editorState.getSelection();

    const selectionState = oldSelectionState.merge({
        focusOffset: props.children[0].props.start + props.decoratedText.length,
        anchorOffset: props.children[0].props.start
    });

    const newContentState = Modifier.applyEntity(
        contentstate,
        selectionState,
        entityKey
    );

    const withBlank = Modifier.replaceText(
        newContentState,
        selectionState,
        emojiShortName + " ",
        null,
        entityKey
    );

    const newEditorState = EditorState.push(
        editorState,
        withBlank,
        "apply-entity"
    );

    props.setEditorState(newEditorState);
}

有什么办法可以优化它吗?谢谢

最佳答案

我不确定这是否是任何实际性能问题的根源,但有两件事看起来很有趣:

  • 通过正则表达式匹配表情符号装饰器,即使您正在为它们创建实体。
  • 在装饰器呈现期间更改编辑器状态(通过 setEntity)。渲染函数 should be pure .

我想您会进行此类处理,因为表情符号可能会通过复制粘贴或某种原生表情符号选择器插入。更好的方法是:

  1. 使用 setEntity 逻辑为表情符号插入实体作为 onChange 的一部分 – 在内容保存和最终呈现之前。
  2. 使用仅基于实体的装饰器策略,例如:
const emojiStrategy = (contentBlock, callback, contentState) => {
    contentBlock.findEntityRanges(character => {
        const entityKey = character.getEntity();
        return (
            entityKey !== null &&
            contentState.getEntity(entityKey).getType() === 'emoji'
        );
    }, callback);
};

然后您的装饰器组件将不需要在渲染期间更新编辑器状态。您也可能不再需要使用 decorateComponentWithProps


现在回到性能——您要确定如何改进它的最佳方式是 profile your app .您将能够准确判断出在击键过程中渲染哪些内容需要时间,然后追踪问题。

关于javascript - 由于装饰器过多,随着内容的增加,Draft js Editor 变慢了,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52240569/

相关文章:

javascript - 在 .js 文件中获取应用程序根 URL

Javascript 继承——在构造函数中声明的对象在实例之间共享?

javascript - Cordova - 拒绝执行内联事件处理程序,因为它违反了以下内容安全策略

reactjs - 部署到 Github Pages 后,_next Assets 出现 404

javascript - 使 document.execCommand ('insertText' , false, 'message' ) 与 Draftjs 一起使用?

javascript - 如何在 Facebook Draft.js 中使用装饰器创建 Link 实体

javascript - 如何通过jquery创建选择框

reactjs - 仅当文件类型更改时,react-file-viewer 才会重新渲染

javascript - 只能更新已安装或正在安装的组件错误。条件渲染