MutationObserver监听文本是否修改

2023-07-311777次阅读原生Jsjavascript

MutationObserver是用于监视 DOM 树内的特定节点的 Web API 接口,一旦监测到节点发生变化,就会通知回调函数执行相应的逻辑。该 API 的兼容性很好。

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <meta
      name="viewport"
      content="width=device-width,initial-scale=1,maximum-scale=1,minimum-scale=1,user-scalable=no"
    />
    <title>Web 富文本编辑器 iframe 实现方式</title>
    <meta content="black" name="apple-mobile-web-app-status-bar-style" />
    <meta content="telephone=no" name="format-detection" />
    <style>
      html,
      body {
        height: 100%;
      }
    </style>
  </head>
  <body>
    源码显示区
    <textarea id="txtYuan" style="width:600px;height:200px"> </textarea>
    <p>
      实时编辑区
      <iframe
        id="editor"
        width="600px"
        height="200px"
        style="border: solid 1px"
      ></iframe>
    </p>
    <input
      type="text"
      id="path"
      value="https://www.google.com.hk/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png"
    />
    <p>
      <input type="button" id="insert_img" value="插入图片" />
      <!-- <input type="button" id="preview" value="预览" />
      <input type="button" id="btnYuan" value="显示源码" /> -->
      <input type="button" id="btnB" value="加粗/正常" />
      <input type="button" id="btnLink" value="添加链接" />
      <input type="button" id="btnBg" value="添加背景色" />
      <input type="button" id="btnItalic" value="斜体字" />
      <input type="button" id="btnUnderline" value="加下划线" />
    </p>

    预览区
    <div style="border: 1px dashed #ccc; padding: 20px" id="preview_area"></div>
    <script>
      const iframe = document.getElementById("editor");
      iframe.contentWindow.document.designMode = "on";
      iframe.contentWindow.document.contentEditable = true;

      // 在iframe中插入一张图片
      document
        .getElementById("insert_img")
        .addEventListener("click", function () {
          iframe.contentWindow.document.execCommand(
            "insertImage",
            false,
            document.getElementById("path").value
          );
          // return;
          // // 返回插入符号当前位置的selection对象
          // const selection = iframe.contentWindow.getSelection();
          // // 获取包含当前节点的文档片段
          // const range = selection.getRangeAt(0);
          // // 创建需追加到光标处节点的文档片段
          // const fragment = range.createContextualFragment(
          //   `<img src="${document.getElementById("path").value}" alt="">`
          // );
          // // 将创建的文档片段插入到光标处
          // range.insertNode(fragment.lastChild);
        });

      // DOM 变动观察器(Mutation observer)
      const fun = function () {
        document.getElementById("preview_area").innerHTML =
          iframe.contentWindow.document.body.innerHTML;
        document.getElementById("txtYuan").innerHTML =
          iframe.contentWindow.document.body.innerHTML;
      };
      const observerOptions = {
        childList: true, // 观察目标子节点的变化,是否有添加或者删除
        attributes: true, // 观察属性变动
        subtree: true, // 观察后代节点,默认为 false
        characterData: true, //观察文本内容
      };
      const observer = new MutationObserver(function (MutationRecord) {
        console.log("MutationRecord", MutationRecord);
        window.requestAnimationFrame(fun);
      });
      observer.observe(iframe.contentWindow.document.body, observerOptions);

      //加粗/正常
      document.getElementById("btnB").addEventListener("click", function () {
        iframe.contentWindow.document.execCommand("bold", false, null);
      });

      //添加链接
      document
        .getElementById("btnUnderline")
        .addEventListener("click", function () {
          iframe.contentWindow.document.execCommand("underline", false, null);
        });

      //添加背景色
      document.getElementById("btnBg").addEventListener("click", function () {
        iframe.contentWindow.document.execCommand(
          "hiliteColor",
          false,
          "#ff0000"
        );
      });
      //斜体字
      document
        .getElementById("btnItalic")
        .addEventListener("click", function () {
          iframe.contentWindow.document.execCommand("italic", false, null);
        });

      //加下划线
      document
        .getElementById("btnItalic")
        .addEventListener("click", function () {
          iframe.contentWindow.document.execCommand("italic", false, null);
        });
      //视图/源码
      document.getElementById("btnHtml").addEventListener("click", function () {
        iframe.contentWindow.document.execCommand("html", false, null);
      });
    </script>
  </body>
</html>
observer.observe(node, config);

config 是一个具有布尔选项的对象,该布尔选项表示“将对哪些更改做出反应”:

  • childList —— node 的直接子节点的更改,
  • subtree —— node 的所有后代的更改,
  • attributes —— node 的特性(attribute),
  • attributeFilter —— 特性名称数组,只观察选定的特性。
  • characterData —— 是否观察 node.data(文本内容),

参考引用 :

https://zh.javascript.info/mutation-observer

https://zhuanlan.zhihu.com/p/622025008

https://developer.mozilla.org/zh-CN/docs/Web/API/MutationObserver

上一篇: React Router v6版中useHistory由useNavigate替代了  下一篇: Range.extractContents()提取并删除选中的对象  

MutationObserver监听文本是否修改相关文章