首先,让我描述一下您目前的做法(2018 年 1 月)。请记住,CKEditor 5 现在正在进行重大重构,事情将会发生变化。最后,我将描述我们完成重构后的样子。如果您不介意等待更多时间让重构结束,您可以跳到后面的部分。
编辑:该1.0.0-beta.1
版本于 3 月 15 日发布,因此您可以跳转到“自 2018 年 3 月以来”部分。
至 2018 年 3 月(至1.0.0-alpha.2
)
(如果您需要了解有关某些类 API 或事件的更多信息,请查看文档。)
您最好的选择是简单地遍历插入的范围。
let data = '';
for ( const child of data.range.getItems() ) {
if ( child.is( 'textProxy' ) ) {
data += child.data;
}
}
请注意,TextProxy
当您遍历范围时,始终会返回一个实例,即使整个Text
节点都包含在范围内。
(您可以阅读更多关于在CKEditor5 和 Angular2 中对范围进行字符串化 - 在编辑器内单击获取插入符号的确切位置以获取数据。)
请记住,这InsertOperation
可能会插入多个不同类型的节点。大多数情况下,这些只是单个字符或元素,但可以提供更多节点。这就是为什么data.item
在data
. 可能有,data.items
但那些将与Array.from( data.range.getItems() )
.
做改变Document#change
之后你没有提到你想用这些信息做什么。获取范围的内容很容易,但是如果您想以某种方式对这些更改做出反应并更改模型,那么您需要小心。当change
事件被触发时,可能已经有更多的更改入队。例如:
- 协作服务可以立即进行更多更改,
- 不同的功能可能已经对相同的更改做出反应并将其更改排队,这可能会使模型不同。
如果您确切地知道您将使用哪些功能集,您可能会坚持我的建议。请记住,您对模型所做的任何更改都应该在一个Document#enqueueChanges()
块中完成(否则,它不会被渲染)。
如果您希望此解决方案防弹,您可能必须这样做:
- 在对子节点进行迭代时
data.range
,如果您找到 a TextProxy
,则在该节点上创建一个LiveRange
跨越。
- 然后,在一个
enqueueChanges()
块中,遍历存储LiveRange
的 s 和他们的孩子。
- 为每个找到的
TextProxy
实例执行逻辑。
- 之后记住
destroy()
所有的LiveRange
s。
如您所见,这似乎不必要地复杂。提供开放和灵活的框架(如 CKE5)存在一些缺点,考虑到所有边缘情况就是其中之一。然而,它确实可以更简单,这就是我们首先开始重构的原因。
自 2018 年 3 月起(从 开始1.0.0-beta.1
)
1.0.0-beta.1 中的重大变化将是引入model.Differ
类、改进的事件结构和模型大部分的新 API。
首先,Document#event:change
将在所有enqueueChange
块完成后被解雇。这意味着您不必担心另一个更改是否会与您在回调中做出反应的更改混淆。
此外,engine.Document#registerPostFixer()
还将添加方法,您将能够使用它来注册回调。event 仍然可用,但event 和change
之间会有细微差别(我们将在指南和文档中介绍它们)。change
registerPostFixer
其次,您将可以访问一个model.Differ
实例,该实例将存储第一次更改之前的模型状态与您想要对更改做出反应时的模型状态之间的差异。您将遍历所有差异项并检查到底发生了什么变化以及在哪里发生了变化。
除此之外,重构中还将进行许多其他更改,下面的代码片段也将反映它们。所以,在新的世界里,它会是这样的:
editor.document.registerPostFixer( writer => {
const changes = editor.document.differ.getChanges();
for ( const entry of changes ) {
if ( entry.type == 'insert' && entry.name == '$text' ) {
// Use `writer` to do your logic here.
// `entry` also contains `length` and `position` properties.
}
}
} );
就代码而言,它可能比第一个片段中的要多一些,但是:
- 第一个片段不完整。
- 在新方法中需要考虑的边缘情况要少得多。
- 新方法更容易掌握 - 在所有更改都完成后您就可以使用所有更改,而不是在其他更改排队并可能弄乱模型时对更改做出反应。
是一个对象,将writer
用于对模型进行更改(而不是Document#batch
API)。它将具有insertText()
, insertElement()
,remove()
等方法。
您可以检查model.Differ
API 和测试,因为它们已经在master
branch上可用。(内部代码会改变,但 API 会保持原样。)