Draft JS Editor становится медленнее по мере увеличения контента из-за большого количества декораторов - PullRequest
0 голосов
/ 09 сентября 2018

Так что мой проект draft-js становится очень медленным (хакерским) при добавлении большего количества контента (после примерно 20 замен декоратора).Я предполагаю, что это происходит из-за декоратора, который проверяет все содержимое редактора с помощью регулярных выражений и заменяет совпадения компонентом emoji каждый раз, когда изменяется состояние.Я также создаю сущности для каждого совпадения, найденного регулярным выражением, я делаю это, украшая компонент с состоянием редактора в качестве реквизита.Есть ли способ сделать это быстрее?Вот мой декоратор:

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

вот мой emojiStrategy:

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

Как я могу оптимизировать это?Спасибо

1 Ответ

0 голосов
/ 16 сентября 2018

Я не уверен, может ли это быть источником реальной проблемы с производительностью, но есть две вещи, которые кажутся забавными:

  • Соответствует декоратору эмодзи с помощью регулярных выражений, даже если вы создаете для них сущности.
  • Изменение состояния редактора (через setEntity) во время рендеринга декоратора. Функции рендеринга должны быть чистыми .

Я полагаю, вы выполняете этот тип обработки, потому что эмодзи могут быть вставлены с помощью копирования-вставки или с помощью какого-либо собственного средства выбора смайликов. Лучшим способом было бы:

  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.


Теперь вернемся к производительности - лучший способ узнать наверняка, как ее улучшить, - профилировать приложение . Вы сможете точно определить, что требуется для визуализации во время нажатия клавиш, а затем отследить проблему.

...