【问题标题】:How do I change slate editor value using Javascript (DOM manipulation)如何使用 Javascript(DOM 操作)更改 slate 编辑器值
【发布时间】:2022-04-22 07:49:28
【问题描述】:

我想通过 Javascript 使用 DOM 操作来更改 slate 编辑器中的文本。

动态更改填充到特定网页中可编辑组件中的值。 该网站结合了简单的输入元素和石板编辑器。一旦焦点离开它们,输入到这些字段中的值就会被保存。

我已经设法更改了普通输入元素的文本并模糊了保存的数据。 我不确定如何在 slate 编辑器元素上实现相同的行为。

我曾尝试使用 dispatchEvent 在 slate 编辑器组件上调度事件,但没有成功。

<div
  data-slate-editor="true"
  data-key="18"
  contenteditable="true"
  class="
    uta_c_editor__slate-editor uta_c_editor__slate-editor--dictation-disabled
  "
  autocorrect="on"
  spellcheck="false"
  role="textbox"
  data-gramm="false"
  style="
    outline: none;
    white-space: pre-wrap;
    overflow-wrap: break-word;
    -webkit-user-modify: read-write-plaintext-only;
  "
>
  <div data-slate-object="block" data-key="19" style="position: relative">
    <span data-slate-object="text" data-key="20"
      ><span data-slate-leaf="true" data-offset-key="20:0"
        ><span data-slate-string="true">Testing in progress.</span></span
      ></span
    >
  </div>
</div>

尝试在此元素上调度以下事件。

let changeEvent = new Event('change', { 
'bubbles': true, 
'detail': {
    value: "Testing Slate Js"
 } });

targetSlateElement.dispatchEvent(changeEvent)

尝试更新其 textContent 如下:

targetSlateElement.textContent = "Testing Slate JS"

上述方法确实改变了它的内容值,但是在模糊它时它会将内容重置为旧内容。

【问题讨论】:

  • 请添加您尝试过的示例代码或指向codepen/codesandbox的链接。
  • @VijayDev 我在 slate js 编辑器的目标元素上调度了以下事件。 let changeEvent = new Event('change', { 'bubbles': true, 'detail': {value: "Testing Slate Js"} });
  • @saichaitanya 在codesandbox.io/s/0qor7onxy0 上的最小重现性会很好。
  • @saichaitanya 只是好奇,你不需要一个由 dispatchEvent("change", ...) 触发的 change 事件处理程序吗?
  • 例如,你可以在MDN doc看到这里

标签: javascript reactjs slate.js


【解决方案1】:

这很糟糕,并且已被弃用,但这里有一种方法:

let selection = window.getSelection();
selection.removeAllRanges();
// remove any current selections
// and then select all children of the slate editor
for (let child of slateElement.children) {
    let range = document.createRange();
    range.selectNode(child);
    selection.addRange(range);
}
// finally use document.execCommand to put our desired replacement text in.
document.execCommand('insertText', false, 'Replacement Text');

(请注意,如果您选择的是要更改其文本的特定子节点,而不是整个 slate 编辑器,则只需选择那个节点)

正如我所提到的,它已被弃用,它使用 document.execCommand,它目前适用于所有主要浏览器,但没有说什么时候会停止。

【讨论】:

    【解决方案2】:

    一种方法是将文本直接写入相应组件的内部memoizedProps 属性。这也是 BTTV 浏览器插件在 Twitch 上的工作方式。

    有关 Slate 编辑器中的 DOM 外观的示例,您可以自行查看 example page

    要获取编辑器节点,您可以从 document.querySelector('div[role="textbox"]'); 开始。

    然后您需要在memoizedProps 中找到保存正确数据的节点。您可以使用BTTV plugin 中的以下辅助函数:

    function getChatInput(element = null) {
        let chatInput;
        try {
            chatInput = searchReactParents(
                getReactInstance(element),
                (n) => n.memoizedProps
                          && n.memoizedProps.componentType != null
                          && n.memoizedProps.value != null
            );
        } catch (_) {}
        return chatInput;
    }
    
    function getReactInstance(element) {
        for (const key in element) {
            if (key.startsWith('__reactInternalInstance$')) {
                return element[key];
            }
        }
        return null;
    }
    
    function searchReactParents(node, predicate, maxDepth = 15, depth = 0) {
        try {
            if (predicate(node)) {
                return node;
            }
        } catch (_) {}
        if (!node || depth > maxDepth) {
            return null;
        }
        const {return: parent} = node;
        if (parent) {
            return searchReactParents(parent, predicate, maxDepth, depth + 1);
        }
        return null;
    }
    

    当你找到正确的节点后,你可以像下面的例子那样设置文本(它使用了来自another function from the BTTV plugin的一些行):

    var textbox = document.querySelector('div[role="textbox"]');
    var textboxInput = getChatInput(textbox);
    if (textboxInput == null) {
        return;
    }
    var text = 'example text set in slate editor';
    textboxInput.memoizedProps.value = text;
    textboxInput.memoizedProps.setInputValue(text);
    textboxInput.memoizedProps.onValueUpdate(text);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-01
      • 2020-03-30
      • 1970-01-01
      • 1970-01-01
      • 2011-01-12
      • 2018-08-09
      相关资源
      最近更新 更多