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