In Slate.js editor.apply(operation) 未正确应用 "split_node" 操作
In Slate.js editor.apply(operation) is not applying "split_node" operations correctly
我正在设计一个 google-doc 类协作工具,使用最新的 React + Slate 作为前端,在后端使用 Flask。我在 React 中使用 socket-io 并在 Python 中使用 flask_socketio 来发出和收听来自其他协作者的内容。
反应应用程序代码:
const RichTextExample = props => {
const [value, setValue] = useState(props.currentEditor);
const editor = useMemo(() => withHistory(withReact(createEditor())), []);
const id = useRef(`${Date.now()}`);
const remote = useRef(false);
const socketchange = useRef(false);
useEffect(() => {
socket.on("new-remote-operations", ({ editorId, ops, doc_id }) => {
if (id.current !== editorId && doc_id === props.document.doc_id) {
remote.current = true;
JSON.parse(ops).forEach(op => {
console.log("LISTEN: applying op", op);
editor.apply(op);
});
remote.current = false;
console.log('value is ', value);
socketchange.current = true; //variable to track socket changes in editor via operations
}
});}, [])
return(
<Slate
editor={editor}
value={value}
onChange={value => {
setValue(value);
const ops = editor.operations
.filter(o => {
if (o) {
return o.type !== "set_selection" && o.type !== "set_value";
}
return false;
});
if (ops.length && !remote.current && !socketchange.current) {
console.log("EMIT: Editor operations are ", ops);
socket.emit("new-operations", {
editorId: id.current,
ops: JSON.stringify(ops),
doc_id: props.document.doc_id
});
}
socketchange.current = false;
}}
>
Python套接字代码很简单:
app = Flask(__name__)
db_name = 'userdoc.db'
app.config['SECRET_KEY'] = 'secret-key'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///'+db_name
socketio = SocketIO(app, cors_allowed_origins="*")
@socketio.on('new-operations', namespace='/')
def operations(data):
print('operations listened...1/2/3..')
emit('new-remote-operations', data, broadcast=True, include_self=False)
Issue:
When split_node is passed as an type of operation in socket.on(),
editor.apply(op) doesn't apply it as it suppose to. Please help me on this.
因此,我得到以下两种情况:
我认为你面临的问题是因为你发送了一批不应该一个一个应用的操作。
一个 split_node
操作,就像您通过点击 enter
生成的操作一样,实际上将拆分所有嵌套节点,直到它到达叶子,并四处移动一些节点。
具体来说,一个split_node其实就是2-3个操作依次进行,不能单独应用。例如,如果您应用第一个,那将拆分文本节点,并最终导致两个 Text
共享相同的属性。 Slate 将规范化它们并尽快重新合并它们,在您的情况下,这发生在每个 editor.apply(op)
.
之间
我认为这里的解决方案就是将整个循环包装在 withoutNormalizing
方法中。它将阻止 Slate 在操作之间规范化文档。
对于板岩 <= 0.47
editor.withoutNormalizing(() => {
JSON.parse(ops).forEach(op => {
editor.apply(op);
});
})
对于石板 >= 0.5
Editor.withoutNormalizing(editor, () => {
JSON.parse(ops).forEach(op => {
editor.apply(op);
});
})
我正在设计一个 google-doc 类协作工具,使用最新的 React + Slate 作为前端,在后端使用 Flask。我在 React 中使用 socket-io 并在 Python 中使用 flask_socketio 来发出和收听来自其他协作者的内容。 反应应用程序代码:
const RichTextExample = props => {
const [value, setValue] = useState(props.currentEditor);
const editor = useMemo(() => withHistory(withReact(createEditor())), []);
const id = useRef(`${Date.now()}`);
const remote = useRef(false);
const socketchange = useRef(false);
useEffect(() => {
socket.on("new-remote-operations", ({ editorId, ops, doc_id }) => {
if (id.current !== editorId && doc_id === props.document.doc_id) {
remote.current = true;
JSON.parse(ops).forEach(op => {
console.log("LISTEN: applying op", op);
editor.apply(op);
});
remote.current = false;
console.log('value is ', value);
socketchange.current = true; //variable to track socket changes in editor via operations
}
});}, [])
return(
<Slate
editor={editor}
value={value}
onChange={value => {
setValue(value);
const ops = editor.operations
.filter(o => {
if (o) {
return o.type !== "set_selection" && o.type !== "set_value";
}
return false;
});
if (ops.length && !remote.current && !socketchange.current) {
console.log("EMIT: Editor operations are ", ops);
socket.emit("new-operations", {
editorId: id.current,
ops: JSON.stringify(ops),
doc_id: props.document.doc_id
});
}
socketchange.current = false;
}}
>
Python套接字代码很简单:
app = Flask(__name__)
db_name = 'userdoc.db'
app.config['SECRET_KEY'] = 'secret-key'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///'+db_name
socketio = SocketIO(app, cors_allowed_origins="*")
@socketio.on('new-operations', namespace='/')
def operations(data):
print('operations listened...1/2/3..')
emit('new-remote-operations', data, broadcast=True, include_self=False)
Issue:
When split_node is passed as an type of operation in socket.on(), editor.apply(op) doesn't apply it as it suppose to. Please help me on this.
因此,我得到以下两种情况:
我认为你面临的问题是因为你发送了一批不应该一个一个应用的操作。
一个 split_node
操作,就像您通过点击 enter
生成的操作一样,实际上将拆分所有嵌套节点,直到它到达叶子,并四处移动一些节点。
具体来说,一个split_node其实就是2-3个操作依次进行,不能单独应用。例如,如果您应用第一个,那将拆分文本节点,并最终导致两个 Text
共享相同的属性。 Slate 将规范化它们并尽快重新合并它们,在您的情况下,这发生在每个 editor.apply(op)
.
我认为这里的解决方案就是将整个循环包装在 withoutNormalizing
方法中。它将阻止 Slate 在操作之间规范化文档。
对于板岩 <= 0.47
editor.withoutNormalizing(() => {
JSON.parse(ops).forEach(op => {
editor.apply(op);
});
})
对于石板 >= 0.5
Editor.withoutNormalizing(editor, () => {
JSON.parse(ops).forEach(op => {
editor.apply(op);
});
})