首页 > 解决方案 > 没有在 DOM 中加载的 document.createElement

问题描述

有没有办法在不运行代码的情况下创建可解析的 Dom?我会解释未来;

我收到一大堆 CK 编辑器创建的代码作为 HTML,但想从中解析元素以创建指定的视图。例如,我想将第一段作为简介,将第一个图像作为主要图像。我还想检索所有图像以创建画廊。

为此,我创建了一个简单但有效的函数:

export const getFromContent = (html, qsa) => {
    const elm = document.createElement("DIV");
    elm.innerHTML = html;
    let r = elm.querySelectorAll(qsa);
    return r;
}

这项工作几乎完美 - 唯一的问题是将所有内容添加到 DOM(我正确使用该术语吗?),这意味着所有资源都会被加载,即使它没有显示在页面上。

在我的示例中,我想在显示之前通过 //res.cloudinary.com/ com 压缩图像加载所有图像,但由于所有图像都已加载,因此这不是必需的。

有没有办法只用基本的 JS 来保持这个好的“版本”?

PS:我知道我可以使用 REGEX 将所有“src”重写为“presrc”,但我真的很想在不更改代码的情况下这样做,从而为错误创造空间。

最好的问候理查德

标签: javascriptecmascript-6jquery-selectorscreateelement

解决方案


这项工作几乎完美 - 唯一的问题是将所有内容添加到 DOM...

它创建 DOM 元素(这就是你这样做的原因!),但它不会将它们添加到窗口的文档中。该代码不会加载引用的图像src或引用的样式表href,并且不会在script元素中运行代码。那些img//元素将在您创建的文件中,但link不在文档中。在图像和样式表的情况下,如果您将它们放入文档中,它们会被加载(即使在那时元素也不会被执行),但不是在此之前。scriptdivdivdivscript

也就是说,您可能想看看 using DOMParser

export const getFromContent = (html, qsa) => {
    const dom = DOMParser.parseFromString(html, "text/html");
    let r = dom.querySelectorAll(qsa);
    return r;
}

再次注意,NodeList如果querySelectorAll将这些元素添加到窗口的document.


注意:当接受用户输入并将其呈现为 HTML 时,在使用之前清理输入以删除不需要的内容通常很重要。例如,我提到script不会评估元素,这是真的,但如果内容包含<img src="javascript:doSomethingNefarious()">在其中,并且您将该图像附加到文档(直接或间接),doSomethingNefarious()则将执行该代码。同样,<div onclick="doSomethingNefarious()">x</div>

如果你搜索“HTML sanitizer”,你会发现很多不同的库都说他们会为你做这件事。但是,这个问题非常重要,一种方法是在被标准化为Sanitization API的过程中。还处于早期阶段,但这是一个非常有前途的发展。使用当前(非常草稿)形式的 API,您可以执行以下操作:

export const getFromContent = (html, qsa) => {
    const div = document.createElement("div");
    div.setHTML(html);  // <== `setHTML` is a new method that sanitizes.
                        // Here I'm using the default sanitizer, but you
                        // could create one with your own custom settings
                        // and pass it as the second argument
    let r = div.querySelectorAll(qsa);
    return r;
}

但 API 仍在不断变化。


推荐阅读