如何初始化 CodeMirror 绑定到 yjs 的值?

How to initialize value of CodeMirror binding to yjs?

我的主要问题是在我的网站上初始化代码编辑器 (CodeMirror) 的 text/value,而不影响我 save/send POST 向我的后端请求的方式。以下是我用于 POST 请求的哈巴狗代码:

p
  form(id='form' method='POST', action='/docs/edit/'+docs._id)
    textarea(name="doo" id="content" style="display: none;")=docs.content
    textarea(name="foo" id="editortext" style="display: none;")
    input.btn.btn-primary(type='submit' value='Save Doc')

我在这里要做的是将 docs.content 发送到 ID 为 "content" 的文本区域,这样我就可以使用它来初始化我的代码编辑器的值,然后将内容放入文本区域的代码编辑器中有什么 "editortext" 单击提交按钮后。因此,POST 请求将从两个文本区域获取数据,然后我可以将 "editortext" 文本区域的内容保存到我的数据库中。 rollup transpilation 后,代码编辑器的逻辑在同一 pug 文件中引用到 javascript 文件。以下是预编译代码的一部分:

/* eslint-env browser */

import * as Y from 'yjs'
import { WebsocketProvider } from 'y-websocket'
import { CodeMirrorBinding } from 'y-codemirror'
import CodeMirror from 'codemirror'
import 'codemirror/mode/clike/clike.js'

window.addEventListener('load', () => {
  const ydoc = new Y.Doc()
  const provider = new WebsocketProvider(
    `${location.protocol === 'http:' ? 'ws:' : 'wss:'}${location.host}`,
    'codemirror',
    ydoc
  )
  const yText = ydoc.getText('codemirror')
  const editorContainer = document.createElement('div')
  editorContainer.setAttribute('id', 'editor')
  document.body.insertBefore(editorContainer, null)
  let content = document.getElementById("content").value
  const editor = CodeMirror(editorContainer, {
    mode: 'text/x-java',
    lineNumbers: true
  })

  editor.setValue(content)

  document.getElementById("form").onsubmit = function(evt){
    document.getElementById("editortext").value = editor.getValue();
  }

大部分代码来自 yjs-codemirror 演示,除了内容变量的声明、setValue 方法的调用和 document.getElementById("form") 块。这段代码目前所做的是向我的数据库发送正确的信息。但是,当我打开文档时,我无法初始化代码编辑器的值。 setValue 方法不起作用,执行以下操作也不起作用:

  const editor = CodeMirror(editorContainer, {
    value: content,
    mode: 'text/x-java',
    lineNumbers: true
  })

即使我用一些字符串替换内容变量,所有前面的例子都会失败。唯一似乎有效的是以下内容:

  const editor = CodeMirror(editorContainer, {
    mode: 'text/x-java',
    lineNumbers: true
  }).setValue(content)

但是,问题是出于某种原因,我在控制台浏览器中收到以下错误:

TypeError: codeMirror is undefined (y-codemirror.js:160:4)
TypeError: editor is undefined (index.js:28:10)

作为参考,我在这个问题中显示的 javascript 全部来自 index.js 文件。无论如何,因为编辑器未定义,我不能再将我的 "editortext" textarea 的值设置为 CodeMirror Textarea 并且我不能将写入代码编辑器的内容保存到我的数据库中。我不确定为什么会发生这种情况,我不确定这是否是 yjs 的 CodeMirrorBinding 特有的,但我们将不胜感激任何对此的帮助。

以下内容引自dmonad,他是Yjs的开发者之一。对于有关 Yjs 的任何技术问题的未来参考,您可能会更好地询问 here,因为 Whosebug 上还没有 Yjs 的标签。

嗨@notemaster,

我假设你的意思是你无法设置 CodeMirror 编辑器的值。

CodeMirrorBinding 将 Y.Text 类型的值绑定到 CodeMirror 实例。 setValue 方法有效,但编辑器的值被绑定覆盖:

ytext.insert(0, 'ytext')
const editor = CodeMirror(..)
editor.setValue('my value')
editor.value() // => "my value"
new CodeMirrorBinding(editor, ytext)
editor.value() // => "ytext value"

我建议你设置值它已绑定到YText类型。

另一个注意事项:Yjs 中没有默认值。最初,Yjs 文档在与服务器同步之前是空的。所以你可能想等到客户端与服务器同步后再设置值。

const setDefaultVal = () => {
  if (ytext.toString() === '') {
    ytext.insert(0, 'my default value')
  }
}
if (provider.synced) {
  setDefaultVal()
} else {
  provider.once('synced', setDefaultVal)
}
 const editor = CodeMirror(editorContainer, {
  mode: 'text/x-java',
  lineNumbers: true
}).setValue(content)

我假设 editor.setValue() returns undefined 。这就是绑定不起作用的原因,您可以设置编辑器的初始值。