我正在使用Draft.js开发一个富文本编辑器(太好了!)。以下代码(允许用户编辑链接)在逻辑上可以正常工作,但我对用户体验感到不满意。
如果用户选择链接的一部分并运行此代码,则此代码会将该链接分为多个链接,这不是用户想要的。
例如,如果将“购买此书”阶段与URL-A链接,并且用户选择“购买此书”并将其更改为URL-B,则该部分将与URL-B链接,但是“书”仍与URL-A链接。
理想情况下,当用户选择链接文本的一部分时,我想自动将选择范围扩展到整个链接,然后执行此代码。
但是,我无法弄清楚该怎么做(将选择范围扩展到整个链接)。
editLink = () => {
const { editorState } = this.state;
const selection = editorState.getSelection();
if (selection.isCollapsed()) {
return;
}
let url = ''; // default
const content = editorState.getCurrentContent();
const startKey = selection.getStartKey();
const startOffset = selection.getStartOffset();
const blockWithLinkAtBeginning = content.getBlockForKey(startKey);
const linkKey = blockWithLinkAtBeginning.getEntityAt(startOffset);
if (linkKey) {
const linkInstance = content.getEntity(linkKey);
url = linkInstance.getData().url;
}
let link = window.prompt("Paste the link", url);
if (!link) {
console.log("removing link");
const newEditorState = RichUtils.toggleLink(editorState, selection, null);
this.setState({ editorState: newEditorState });
return;
}
console.log("adding a link", link);
const contentWithEntity = content.createEntity('LINK', 'MUTABLE', { url: link });
const entityKey = contentWithEntity.getLastCreatedEntityKey();
const newEditorState = EditorState.set(editorState, { currentContent: contentWithEntity });
const yetNewEditorState = RichUtils.toggleLink(newEditorState, newEditorState.getSelection(), entityKey);
this.setState({ editorState: yetNewEditorState} );
}
非常感谢您的帮助或建议。
答案 0 :(得分:0)
有两种方法可以做到这一点。第一个可能是您要尝试的操作-在当前链接的顶部应用一个新链接,从而覆盖它。这不是最好的方法,但是可以做到。
第二个更简单。在ContentState
对象中,有一个方法replaceEntityData()
。因此,您可以像这样实现它:
editLink = () => {
const { editorState } = this.state;
const selection = editorState.getSelection();
if (selection.isCollapsed()) {
return;
}
let url = ''; // default
const content = editorState.getCurrentContent();
const startKey = selection.getStartKey();
const startOffset = selection.getStartOffset();
const block = content.getBlockForKey(startKey);
const linkKey = block.getEntityAt(startOffset);
let link = window.prompt("Paste the link", url);
if (!link) { //REMOVING LINK
var contentWithRemovedLink = content;
block.findEntityRanges(charData => { //You need to use block.findEntityRanges() API to get the whole range of link
const entityKey = charData.getEntity();
if (!entityKey) return false;
return entityKey === linkKey //Need to return TRUE only for your specific link.
}, (start, end) => {
const entitySelection = new SelectionState({
anchorKey: block.getKey(), //You already have the block key
focusKey: block.getKey(),
anchorOffset: start, //Just use the start/end provided by the API
focusOffset: end })
contentWithRemovedLink = Modifier.applyEntity(content, entitySelection, null)
return;
})
const newEditorState = EditorState.set(
editorState, { currentContent: contentWithRemovedLink });
return;
}
console.log("adding a link", link);
//CHANGING LINK
const contentWithUpdatedLink = content.replaceEntityData(linkKey, { url: link });
const newEditorState = EditorState.set(editorState, { currentContent: contentWithUpdatedLink });
//Now do as you please.
}
删除链接:
在ContentBlock
api上,有一种称为findEntityRanges()
的方法。该函数有两个参数:
(char: CharacterMetadata) => boolean
:characterMetadata对象的过滤器功能(每个连续的ENTITY + INLINE_STYLE组合都有一个唯一的CharacterMetatdata
对象。您可以从此处通过characterMetadata.getEntity()
进入实体。)如果此函数执行为TRUE,则将执行(2)。(start: number, end: number) => void
。这使您可以访问执行TRUE的每个特定字符范围的开始和结束偏移量。现在,您可以开始和结束任何操作。 之后,您可以将NULL实体与包含整个链接的新SelectionState
一起应用。这将删除链接实体。
更改链接:
您已经拥有linkKey
。只需调用content.replaceEntityData(linkKey, {url: "MY NEW URL"})
即可使用新的URL生成新的ContentState
。此处定义的API:https://draftjs.org/docs/api-reference-content-state#replaceentitydata