如何在DraftJS中实现自定义装饰器

时间:2019-04-02 00:46:59

标签: reactjs draftjs

我正在尝试为我的draft.js组件实现自定义装饰器。我不想使用CompositeDecorator,因为我想根据输入渲染许多不同类型的装饰。 除了draft.js储存库中的类型定义-https://github.com/facebook/draft-js/blob/master/src/model/decorators/DraftDecoratorType.js

,我找不到任何有关DraftDecoratorType的文档。

我在https://github.com/SamyPesse/draft-js-prism/blob/master/lib/index.js中得到了启发,因此我决定尝试一些小步骤-只需编写一个装饰器,以#粗体开头的单词即可。

到目前为止,我正在使用的装饰器可以在下面找到。

this.state = {
            editorState: Draft.EditorState.createEmpty({
                getComponentForKey(key: string): Function {
                    const originalText = key.split('.')[0];
                    return () => <b>{originalText}</b>;
                },
                getPropsForKey(key: string): any {
                    return {};
                },

                getDecorations(block: any, contentState: any): any {

                    const text = block.getText();
                    const decorations: Array<string | null> = Array(text.length).fill(null);

                    let counter = 0;
                    let result: RegExpExecArray;

                    const regex = /(^|\s)#\w+/g;
                    while ((result = regex.exec(text) as RegExpExecArray) != null) {
                        const start = result.index;
                        const end = start + result[0].length;
                        decorations.fill(result[0] + '.' + counter, start, end);
                        counter++;
                    }

                    console.log(decorations);
                    return Immutable.List(decorations);
                }
            })
        };

我的组件的完整代码可在https://github.com/d-kozak/react-playground/blob/master/src/draftjs/CustomDecoratorExample.tsx

中找到

不幸的是,当我使用该编辑器时,它的行为开始无法预测。此刻,当我输入#后跟一个字符(例如#a)时,即装饰器被触发时,文本确实变粗体,但是焦点移到了文本区域的开头,之后它的行为就变了非常不可预测很难描述,但实际上您可以在这里自己尝试:https://dkozak-react-playground.netlify.com

我在https://github.com/d-kozak/react-playground/blob/master/src/draftjs/CompositeDecoratorExample.tsx上使用CompositeDecorator实现了基本上相同的装饰器,并且按预期工作。如果打开我的netlify页面,则可以在同一页面的其他选项卡上找到实时演示。

但是我的自定义装饰器中的某些东西完全使编辑器崩溃,但是我不确定为什么以及如何修复它。有人可以帮我吗?

1 个答案:

答案 0 :(得分:0)

我相信解决方法是将 getComponentForKey 的返回值替换为

(props) => <b>{props.children}</b>;

如果您查看子项,您会发现它带有各种键,我假设 Draft.js 使用这些键来确定您是否更改了元素。您的版本不包含这些信息,因此元素可能已重新创建,否则您的光标将被重置,因为它不知道将这个看似新的元素放在哪里。