Mor*_*ori 7 html javascript iframe
这是一个基本的 HTML 编辑器:
textarea,
iframe {
width: 400px;
height: 300px;
}
Run Code Online (Sandbox Code Playgroud)
<textarea></textarea>
<iframe></iframe>
Run Code Online (Sandbox Code Playgroud)
var textarea = document.querySelector('textarea');
function preview() {
var iframeDoc = document.querySelector('iframe').contentDocument;
iframeDoc.open();
iframeDoc.write(textarea.value);
iframeDoc.close();
}
textarea.addEventListener('input', preview);
Run Code Online (Sandbox Code Playgroud)
它会更新您放入的 HTML 和 CSS textarea,但您不能使用 JavaScriptconst或let变量,因为一旦您编辑插入的代码,它就会抛出以下语法错误:
Identifier * has already been declared
要明白我的意思,请将以下示例代码插入到textarea:
<!doctype html>
<html lang="en">
<head>
<title>Sample Code</title>
</head>
<body>
<p>Hello!</p>
<script>
const p = document.querySelector('p');
p.style.color = 'blue';
</script>
</body>
</html>
Run Code Online (Sandbox Code Playgroud)
现在改变Hello!为Hello, world!或blue为red。
有什么解决方案可以让用户继续编辑代码而不会出现该错误?
受到svarlitskiy 的回答的启发,我最终决定iframe用新创建的替换:
function preview() {
var iframe = document.createElement('iframe');
document.querySelector('iframe').replaceWith(iframe);
var iframeDoc = iframe.contentDocument;
iframeDoc.write(textarea.value);
iframeDoc.close();
}
Run Code Online (Sandbox Code Playgroud)
在我看来,有两种主要方法可以做到这一点:使用srcdoc属性(@Kaiido\'s answer)或使用 blob URL。在这个答案中,我将解释这些选项是什么以及它们有何不同。我还将为您提供一个如何使用 blob URL 选项的代码示例。
该srcdoc属性允许您将 iframe 的 HTML 内容写入为字符串。这很简单,但也有一些问题:
\xe2\x80\xa2 某些旧浏览器不支持该srcdoc属性,因此您可能需要使用 src 属性提供后备。
\xe2\x80\xa2 HTML 内容可能包含可能危及主文档安全的恶意脚本或链接。在将 HTML 内容分配给srcdoc属性之前,您可能需要对其进行清理或转义。
因此,如果您不介意此类问题,您可能不需要这个答案,因为使用blobURL 比使用srcdoc.
blob URL 方法涉及从 HTML 内容创建一个新的 blob 对象,然后将其 URL 分配给srciframe 的属性。这种方法可以避免一些兼容性和安全问题:
\xe2\x80\xa2 大多数支持该src属性的浏览器都支持 blob URL,因此您无需担心后备问题。
\xe2\x80\xa2 Blob URL 与主文档分离,并具有自己的来源和权限,因此它无法访问或修改主文档中的任何内容。
\n以下是如何使用 blob URL 方法的代码示例。我使用了一个debounce函数来避免过于频繁地更新 iframe,这可能会导致闪烁。您可以在此处找到有关该debounce功能的更多信息。
function preview() {\n var blob = new Blob([textarea.value], { type: "text/html" });\n var url = URL.createObjectURL(blob);\n iframe.onload = function () {\n URL.revokeObjectURL(url);\n };\n iframe.src = url;\n}\n\n\nvar debounceTimer;\n\nfunction debounce(func, delay) {\n return function () {\n clearTimeout(debounceTimer);\n debounceTimer = setTimeout(func, delay);\n };\n}\n\nvar debouncedPreview = debounce(preview, 300);\n\ntextarea.addEventListener("input", debouncedPreview);\nRun Code Online (Sandbox Code Playgroud)\nfunction preview() {\n var blob = new Blob([textarea.value], { type: "text/html" });\n var url = URL.createObjectURL(blob);\n iframe.onload = function () {\n URL.revokeObjectURL(url);\n };\n iframe.src = url;\n}\n\n\nvar debounceTimer;\n\nfunction debounce(func, delay) {\n return function () {\n clearTimeout(debounceTimer);\n debounceTimer = setTimeout(func, delay);\n };\n}\n\nvar debouncedPreview = debounce(preview, 300);\n\ntextarea.addEventListener("input", debouncedPreview);\nRun Code Online (Sandbox Code Playgroud)\r\nvar textarea = document.querySelector("textarea");\nvar iframe = document.querySelector("iframe");\nvar debounceTimer;\n\nfunction debounce(func, delay) {\n return function () {\n clearTimeout(debounceTimer);\n debounceTimer = setTimeout(func, delay);\n };\n}\n\nfunction preview() {\n var blob = new Blob([textarea.value], { type: "text/html" });\n var url = URL.createObjectURL(blob);\n iframe.onload = function () {\n URL.revokeObjectURL(url);\n };\n iframe.src = url;\n}\n\nvar debouncedPreview = debounce(preview, 300);\n\ntextarea.addEventListener("input", debouncedPreview);Run Code Online (Sandbox Code Playgroud)\r\ntextarea,\niframe {\n width: 400px;\n height: 300px;\n}Run Code Online (Sandbox Code Playgroud)\r\n总之,srcdoc和 blob URL 方法都可用于在 iframe 中创建 HTML 内容的实时预览。该srcdoc方法更简单,但兼容性和安全性较差,而 blob URL 方法更复杂,但兼容性和安全性更高。我更喜欢 blob URL 方法,因为它可以避免旧浏览器和恶意内容的一些潜在问题,但您可以选择适合您的需求和偏好的方法。
据我所知,没有办法在 JS 中取消声明变量或将它们从文档的范围中删除。我建议iframe在每个input事件上动态地重新创建一个元素。像这样的东西:
// index.js
const textarea = document.querySelector("textarea");
function preview() {
const container = document.getElementById("iframe-container");
const existing = document.querySelector("iframe");
if (existing) existing.remove();
const iframe = document.createElement("iframe");
container?.appendChild(iframe);
const iframeDoc = iframe?.contentDocument;
iframeDoc?.open();
iframeDoc?.write(textarea?.value ?? "");
iframeDoc?.close();
}
textarea?.addEventListener("input", preview);
Run Code Online (Sandbox Code Playgroud)
<!-- index.html -->
<textarea></textarea>
<div id="iframe-container">
<iframe></iframe>
</div>
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
668 次 |
| 最近记录: |