简体   繁体   English

在 Slate.js editor.apply(operation) 中没有正确应用“split_node”操作

[英]In Slate.js editor.apply(operation) is not applying "split_node" operations correctly

I am designing a google-doc like collaborative tool with latest React + Slate as Frontend and Flask in Backend.我正在设计一个类似 google-doc 的协作工具,使用最新的 React + Slate 作为前端,后端使用 Flask。 I am using socket-io in React and flask_socketio in Python to emit and listen content from other collaborators.我在 React 中使用 socket-io 和在 Python 中使用 flask_socketio 来发出和收听来自其他合作者的内容。 React app code:反应应用程序代码:

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 code for socket is simple:套接字的 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.当 split_node 作为 socket.on() 中的一种操作类型传递时, editor.apply(op) 不会像它想象的那样应用它。 Please help me on this.请帮我解决这个问题。

Because of this, I get following two cases:因此,我得到以下两种情况: 情况1

在此处输入图片说明 在此处输入图片说明

I think the issue you are facing is because you send a batch of operations that should not be applied one by one.我认为您面临的问题是因为您发送了一批不应逐个应用的操作。

A split_node operation like the one you are generating by hitting enter will actually split all the nested nodes till it reaches the leaves, and move some nodes around.像您通过按enter生成的那样的split_node操作实际上会拆分所有嵌套节点,直到它到达叶子,并移动一些节点。

Concretely, a split_node is actually 2-3 operations following each others, that can't be applied solely.具体来说,一个split_node实际上是2-3个操作,不能单独应用。 If you apply the first one for example, that would split the text node, and end up with two Text sharing the same attributes.例如,如果您应用第一个,这将拆分文本节点,并最终得到两个共享相同属性的Text Slate will normalize them and re-merge them as soon as it can, which in your case, happen between each editor.apply(op) . Slate 将规范化它们并尽快重新合并它们,在您的情况下,这发生在每个editor.apply(op)

I think the solution here, is simply to wrap your whole loop inside the withoutNormalizing method.我认为这里的解决方案只是将整个循环包装在withoutNormalizing方法中。 It will prevent Slate to normalize the document in-between the operations.它会阻止 Slate 在操作之间规范化文档。

For Slate <= 0.47对于 Slate <= 0.47

editor.withoutNormalizing(() => {
  JSON.parse(ops).forEach(op => {
    editor.apply(op);
  });
})

For Slate >= 0.5对于 Slate >= 0.5

Editor.withoutNormalizing(editor, () => {
  JSON.parse(ops).forEach(op => {
    editor.apply(op);
  });
})

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM