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

Posted

技术标签:

【中文标题】在 Slate.js editor.apply(operation) 中没有正确应用“split_node”操作【英文标题】:In Slate.js editor.apply(operation) is not applying "split_node" operations correctly 【发布时间】:2020-05-27 18:03:34 【问题描述】:

我正在设计一个类似 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;
        
      >

socket 的 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)

问题

当 split_node 作为 socket.on() 中的一种操作类型传递时, editor.apply(op) 并没有像想象的那样应用它。请帮我解决这个问题。

因此,我得到以下两种情况:

【问题讨论】:

供将来参考:github.com/ianstormtaylor/slate/issues/3493(我在 Slate repo 上提出了一个问题)。如果有人认为这不是错误,请帮助我理解。谢谢。 【参考方案1】:

我认为你面临的问题是因为你发送了一批不应该一个一个应用的操作。

split_node 操作就像您通过点击 enter 生成的操作一样,实际上会拆分所有嵌套节点,直到它到达叶子节点,然后移动一些节点。

具体来说,一个split_node实际上是2-3个操作相互跟随,不能单独应用。例如,如果应用第一个,则会拆分文本节点,并最终得到两个共享相同属性的Text。 Slate 将尽快将它们标准化并重新合并它们,在您的情况下,这发生在每个 editor.apply(op) 之间。

我认为这里的解决方案是将整个循环包装在 withoutNormalizing 方法中。它会阻止 Slate 在操作之间规范化文档。

对于板岩
editor.withoutNormalizing(() => 
  JSON.parse(ops).forEach(op => 
    editor.apply(op);
  );
)

对于板岩 >= 0.5

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

【讨论】:

谢谢伙计。请提供一些链接以更好地理解 slate >=0.5。

以上是关于在 Slate.js editor.apply(operation) 中没有正确应用“split_node”操作的主要内容,如果未能解决你的问题,请参考以下文章

在Slate.js编辑器中编辑的数据在data based中保存为[Object],[Object]。如何使这个Object成为有意义的内容?

[开发总结]富文本前端框架对比分析

SharedPreferences 未保存在 onPause 方法中

初探富文本之编辑器引擎

一款开源的 Web 富文本编辑器

图论-课堂例题