“无法在 'Selection' 上执行 'addRange':参数 1 不是 'Range' 类型

"Failed to execute 'addRange' on 'Selection': parameter 1 is not of type 'Range'

我想在一个浏览器的 contenteditable div 中镜像文本选择到另一个浏览器。代码的简化和相关部分是:

在源浏览器中:

function someFunc() {
  if (window.getSelection().isCollapsed)
       return;
  var range = window.getSelection().getRangeAt(0);
  
  //Send range over websockets to another browser
  sendToAnotherBrowser(...) //Send range

}

在远程浏览器中,我执行以下代码:

 var sel = window.getSelection();
 sel.addRange(range);  //Where range is the range transmitted over webSockets

我收到以下错误:

 "Failed to execute 'addRange' on 'Selection': parameter 1 is not of type 'Range'

问题: 如何通过 websockets 传输“Range”对象?它不是要字符串化和发送的 JSON 对象。我可以通过某种方式序列化它,将其更改为 base64,然后在接收端反向处理吗?

你不能序列化对象本身,你可以创建一个包含 Range 对象数据的对象,将它发送到套接字并从那里构建一个新的 Range 对象.

const sendRange = range => {
  const {
    startContainer,
    endContainer,
    startOffset, 
    endOffset, 
    collapsed
  } = range;
  const package = JSON.stringify({
    startNodeId: startContainer.id,
    endNodeId: endContainer.id,
    startOffset, 
    endOffset
    collapsed
  });
  sendToAnotherBrowser(package);
}

const range = window.getSelection().getRangeAt(0);
sendRange(range);

并在您构建新对象的其他地方接收它。

const buildRange = package => {
  const { 
    startNodeId,
    endNodeId,
    startOffset, 
    endOffset, 
    collapsed 
  } = JSON.parse(package);
  const selection = window.getSelection();
  const range = document.createRange();
  const startNode = document.getElementById(startNodeId);
  const endNode = document.getElementById(endNodeId);
  range.setStart(startNode, startOffset);
  range.setEnd(endNode, endOffset);
  if (collapsed) {
    range.collapse();
  }
  selection.addRange(range);
}