使用Draft.js插入实体后如何重置后续输入的文本样式
解决方案
这是Draft.js的默认行为:插入带样式/实体的内容后,光标会落在插入内容的末尾,自动继承当前位置的样式和实体关联,导致后续输入复用同样的样式,有三种常用方案可以解决这个问题:
方案1:插入后重置光标位置的样式规则
插入内容前先保存当前选区的原有样式,插入完成后手动把新光标位置的样式覆盖为插入前的样式,同时取消实体关联:
// 插入前先获取当前选区的原始样式 const originalInlineStyle = contentState.getInlineStyleForRange(selectionState); // 原有插入实体逻辑 contentState = Modifier.insertText( contentState, selectionState, '{{1}}', OrderedSet.of('PLACEHOLDER_COLOR'), entityKey ); // 计算插入完成后的新光标位置(插入内容末尾) const newCursorPosition = selectionState.merge({ anchorOffset: selectionState.getAnchorOffset() + '{{1}}'.length, focusOffset: selectionState.getAnchorOffset() + '{{1}}'.length, isBackward: false }); // 重置新光标位置的内联样式为插入前的样式,同时清除实体关联 contentState = Modifier.setInlineStyleOverride(contentState, newCursorPosition, originalInlineStyle); contentState = Modifier.setEntityData(contentState, newCursorPosition, null);
最后用新生成的contentState和newCursorPosition更新EditorState即可。
方案2:插入实体后追加零宽空格做样式隔离
如果不想处理光标样式覆盖逻辑,可以在插入占位符实体后,追加一个零宽空格,单独给这个零宽空格设置为插入前的原始样式、不关联任何实体,后续输入会自动落在零宽空格的位置,继承它的样式:
const originalInlineStyle = contentState.getInlineStyleForRange(selectionState); // 原有插入实体逻辑 contentState = Modifier.insertText( contentState, selectionState, '{{1}}', OrderedSet.of('PLACEHOLDER_COLOR'), entityKey ); // 计算占位符末尾的选区 const afterPlaceholderSelection = selectionState.merge({ anchorOffset: selectionState.getAnchorOffset() + '{{1}}'.length, focusOffset: selectionState.getAnchorOffset() + '{{1}}'.length }); // 插入零宽空格,使用原始样式,不关联任何实体 contentState = Modifier.insertText( contentState, afterPlaceholderSelection, '\u200B', originalInlineStyle, null );
零宽空格不会被用户看到,也不会影响正常的内容长度统计,兼容性更好。
方案3:样式规则层面限制生效范围
如果你的实体是不可变的,可以调整样式规则,只有当字符同时满足有PLACEHOLDER_COLOR样式、且关联了对应实体时才生效,后续输入的字符没有关联实体,自然不会继承样式:
.PLACEHOLDER_COLOR[data-entity-key="你的实体类型"] { color: #999; /* 其他占位符样式 */ }
内容的提问来源于stack exchange,提问作者Tinmar
相关产品推荐
相关产品推荐

