案例:分离视图
尽管可以在一个编辑器状态上创建多个视图,但是视图本身不会同步。编辑器状态是不可变值,如果通过不同视图更新状态很容易发生分歧。
因此,为了保证两个视图的内容同步,您得从一个视图转发变更到另一个。比较好的实现方式是重写分发函数,或者更新监听器。在本案例中,我们使用前者。
确保只有一个视图有撤消历史纪录,我们配置一个状态包含历史纪录拓展,另外一个没有。主编辑器的状态按照正常方式来配置。
javascript
import { EditorState } from "@codemirror/state"
import { defaultKeymap, historyKeymap, history } from "@codemirror/commands"
import { drawSelection, keymap, lineNumbers } from "@codemirror/view"
let startState = EditorState.create({
doc: "The document\nis\nshared",
extensions: [
history(),
drawSelection(),
lineNumbers(),
keymap.of([
...defaultKeymap,
...historyKeymap,
])
]
})
第二个编辑器状态不追踪历史状态,只绑定历史相关按键来执行主编辑器的 撤消/恢复
。
javascript
import {undo, redo} from "@codemirror/commands"
let otherState = EditorState.create({
doc: startState.doc,
extensions: [
drawSelection(),
lineNumbers(),
keymap.of([
...defaultKeymap,
{key: "Mod-z", run: () => undo(mainView)},
{key: "Mod-y", mac: "Mod-Shift-z", run: () => redo(mainView)}
])
]
})
接下来,让我们编写两个编辑器之间的响应变更广播的代码。
为了能够区别用户传递的常规事务和其他编辑器同步过来的事务,我们定义一个注解来标记同步事务。只要有事务让文档变更,就会触发同步视图,并被另外一个编辑器调用。
typescript
import { EditorView } from "@codemirror/view"
import { Transaction, Annotation } from "@codemirror/state"
let syncAnnotation = Annotation.define<boolean>()
function syncDispatch(tr: Transaction, view: EditorView, other: EditorView) {
view.update([tr])
if (!tr.changes.empty && !tr.annotation(syncAnnotation)) {
let annotations: Annotation<any>[] = [syncAnnotation.of(true)]
let userEvent = tr.annotation(Transaction.userEvent)
if (userEvent) annotations.push(Transaction.userEvent.of(userEvent))
other.dispatch({ changes: tr.changes, annotations })
}
}
现在让我们创建两个视图,看看有什效果。
javascript
let mainView = new EditorView({
state: startState,
parent: document.querySelector("#editor1"),
dispatch: tr => syncDispatch(tr, mainView, otherView)
})
let otherView = new EditorView({
state: otherState,
parent: document.querySelector("#editor2"),
dispatch: tr => syncDispatch(tr, otherView, mainView)
})
注意:编辑器之间不同享非文档状态(比如选择状态)。对于大多数这样的状态,都不合适共享。但在某些情况下,可能需要共享其他元素(例如断点信息)。您必须设置同步代码,以便在文档更改的同时将更新转发到共享状态(也可能是效果)。