内联样式和块级样式都不是只是我们想要添加到编辑富中的富内容。例如,Facebook评论输入提供了蓝色背景亮点,用于提及和标签。
为了支持自定义富文本的灵活性,草稿提供了一个“装饰器”系统。推特示例提供了一个现实的装饰器的例子。
(“装饰器是用来添加高级富内容的一种方法”)
CompositeDecorator- 扫描给定的内容块
- 满足定义的匹配策略的文本范围。
- 使用自定义的React组件去呈现他们。
可以使用CompositeDecorator类定义所需的装饰器行为。此类允许您提供多个DraftDecorator对象,并依次搜索每个策略的一组文本。
装饰器存储在EditorState记录中。当创建一个新的EditorState对象,例如 通过EditorState.createEmpty(),可以选择提供装饰器。
基于钩子
当Draft编辑器中的内容更改时,生成的EditorState对象将使用其装饰器评估新的ContentState,
并标识要进行装饰的范围。 此时形成了一个完整的块,装饰器和内联样式,作为我们渲染输出的基础。通过这种方式,我们始终保证随着内容的改变,渲染的装饰与我们的EditorState同步。
例如,在“Tweet”编辑器示例中,我们使用一个CompositeDecorator来搜索@ -handle字符串以及主题标签字符串:
const compositeDecorator = new ComponsiteDecorator([
{
strategy: handleStrategy,
component: HandleSpan,
},
{
strategy: hashtagStrategy,
component: HashtagSpan,
}
])
此复合装饰器将首先扫描给定的文本块以获取@-handle匹配,然后对于hashtag匹配进行扫描。
const HANDLE_REGEX = /\@[\W]+/g;
const HASHTAG_REGEX = /\#[\w\u0590-\u05ff]+/g;
function handleStrategy(contentBlock, callback, contentState){
findWithRegex(HANDLE_REGEX, contentBlock, callback)
}
function hashtagStrategy(contentBlock, callback, contentState) {
findWithRegex(HASHTAG_REGEX, contentBLCOK, callback);
}
function findWithRegex(regex, contenBlock, callback) {
const text = contenBlock.getText();
let matchArr, start;
while((matcArr = regex.exec(text) !== null)) {
start = matchArr.index;
callback(start, start + matchArr[0].length);
}
}
策略函数执行提供的回调与匹配的文本范围的起始和结束值。
Decorator Components对于您装饰的文本范围,您必须定义一个用于呈现它们的React组件。 这些往往是使用 CSS类 或 style 的简单 span 元素。
在我们当前的示例中,CompositeDecorator对象将HandleSpan和HashtagSpan命名为用于装饰的组件。
这些只是基本的无状态组件:
const HandleSpan = (props) => {
return <span {...props} style={styles.handle}>{props.children}</span>
};
const HashtagSpan = (props) => {
return <span {...props} style={styles.hashtag}>{props.children}</span>;
};
注意,props.children被传递到渲染的输出。 这样做是为了确保文本在装饰的范围内呈现。
您可以使用相同的方法进行链接,如我们的链接示例所示。
超越CompositeDecorator提供给EditorState的装饰器对象只需要符合DraftDecoratorType Flow类型定义的期望,这意味着您可以创建任何您想要的装饰器类,只要它们与预期类型相匹配,则不受CompositeDecorator的限制。
设置新的装饰此外,当然,在正常状态传播期间,通过不可变的方式,可以在EditorState上设置新的装饰器值。
这意味着在您的应用程序工作流程中,如果您的装饰器无效或需要修改,您可以创建一个新的装饰器对象(或使用null删除所有装饰)和EditorState.set()以使用新的装饰器设置。
例如,如果由于某种原因,我们希望在用户与编辑器交互时禁用@ -handle装饰的创建,那么执行以下操作会很好:
function turnOffHandleDecorations(editorState) {
const onlyHashtags = new CompositeDecorator([{
strategy: hashtagStrategy,
component: HashtagSpan,
}]);
return EditorState.set(editorState, {decorator: onlyHashtags});
}
将使用新装饰器重新评估此editorState的ContentState,并且@ -handle装饰将不再存在于下一个渲染过程中。
同样,由于不可变对象上的数据持久性,这仍然是内存有效的。