下面是一个基本的HTML编辑器:
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);
textarea,
iframe {
width: 400px;
height: 300px;
}
<textarea></textarea>
<iframe></iframe>
DEMO
它会更新你放在textarea
中的HTML和CSS,但你不能使用JavaScript const
或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>
型
现在将Hello!
更改为Hello, world!
,或将blue
更改为red
。
有什么解决方案可以让用户继续编辑代码而不会出现错误?
更新
受svarlitskiy's answer的启发,我最终决定用一个新创建的iframe
来替换它:
function preview() {
var iframe = document.createElement('iframe');
document.querySelector('iframe').replaceWith(iframe);
var iframeDoc = iframe.contentDocument;
iframeDoc.write(textarea.value);
iframeDoc.close();
}
型
6条答案
按热度按时间d6kp6zgx1#
在我看来,主要有两种方法可以做到这一点:使用
srcdoc
属性(@Kaiido的答案)或使用blob URL。在这个答案中,我将解释这些选项是什么以及它们的区别。我还将给予你一个代码示例,说明如何使用blob URL选项。使用srcdoc
srcdoc
属性允许您将iframe的HTML内容写成字符串。这很简单,但也有一些问题:·一些旧的浏览器不支持
srcdoc
属性,因此您可能需要使用src属性提供后备。HTML内容可能包含恶意脚本或链接,可能会危及主文档的安全性。您可能需要在将HTML内容分配给
srcdoc
属性之前对其进行清理或转义。因此,如果您不介意这样的问题,您可能不需要这个答案,因为使用
blob
URL比使用srcdoc
更复杂和间接。使用blob URL
blob URL方法包括从HTML内容创建一个新的blob对象,然后将其URL分配给iframe的
src
属性。这种方法可以避免一些兼容性和安全性问题:大多数支持
src
属性的浏览器都支持blob URL,因此您无需担心回退。Blob URL与主文档是分开的,并且有自己的来源和权限,因此它不能访问或修改主文档中的任何内容。
示例:
下面是如何使用blob URL方法的代码示例。我使用了一个
debounce
函数来避免过于频繁地更新iframe,这可能会导致 Flink 。您可以找到有关debounce
函数here的更多信息。字符串
总之,
srcdoc
和blob URL方法都可以用于在iframe中创建HTML内容的实时预览。srcdoc
方法更简单,但兼容性和安全性较差,而blob URL方法更复杂,但兼容性和安全性更高。我更喜欢blob URL方法,因为它避免了旧浏览器和恶意内容的一些潜在问题,但您可以选择适合您的需求和偏好的方法。yzxexxkh2#
设置iframe的
srcdoc
,而不是重新打开它的Document
:dxxyhpgq3#
这将允许您输入部分HTML,并且仍然在iframe中呈现页面而不会 Flink 。
HTML
字符串
CSS
型
JS
型
xdnvmnnf4#
另一种方法:
字符串
at0kjp5o5#
据我所知,没有办法在JS中取消声明变量或将它们从文档的范围中删除。我建议在每个
input
事件上动态地重新创建一个iframe
元素。大概是这样的:个字符
ecr0jaav6#
您遇到的问题是由于每次调用iframeDoc.write(textarea.value)时,它都会完全重新创建iframe的内容,包括其JavaScript上下文。这意味着当您修改文本区域中的内容时,新的JavaScript代码会与之前声明的变量发生冲突,从而导致“Identifier has already been declared”错误。
为了解决这个问题,并允许用户继续编辑代码而不会出现错误,您可以使用document.createElement方法创建新的脚本元素,并将它们添加到iframe文档的头部。这样,您就不会覆盖整个iframe内容,并且JavaScript上下文将被保留。
字符串
使用这种方法,当您更新文本区域中的内容时,它只会使用iframeDoc.write()更新iframe中的HTML和CSS部分。iframe内部的JavaScript代码将被提取并单独执行,使用脚本标记上的eval(),允许用户继续编辑代码,而不会遇到“标识符已被声明”错误。