Javascript Can';t使用innerHTML从HTML字符串创建某些类型的节点
以下javascript(在chrome控制台中运行)没有达到我的预期:Javascript Can';t使用innerHTML从HTML字符串创建某些类型的节点,javascript,html,validation,dom,Javascript,Html,Validation,Dom,以下javascript(在chrome控制台中运行)没有达到我的预期: > var elem = document.createElement("foo"); undefined > elem.innerHTML = "<tr></tr>" "<tr></tr>" > elem.outerHTML "<foo></foo>" var elem=document.createElement(“foo”);
> var elem = document.createElement("foo");
undefined
> elem.innerHTML = "<tr></tr>"
"<tr></tr>"
> elem.outerHTML
"<foo></foo>"
var elem=document.createElement(“foo”);
未定义
>elem.innerHTML=“”
""
>外层元素
""
标记已消失
这似乎是特定于表相关元素的。使用
或
可以正常工作
我认为我所做的是无效的,因为“foo”不是一个已知的元素,可能与表相关的元素只能出现在一个表中。有趣的是,以下代码工作得很好:
> var elem = document.createElement("foo"), tr = document.createElement("tr");
> elem.appendChild(tr);
> elem.outerHTML
"<foo><tr></tr></foo>"
var elem=document.createElement(“foo”),tr=document.createElement(“tr”);
>附肢儿童元素(tr);
>外层元素
""
因此,似乎构造本身(不在
中的
)是允许的,但是使用innerHTML将其放置在其中的方法不起作用-也许这需要经过一些html清理,删除不严格的内容,而直接创建DOM节点则不受相同的验证
我的问题:是否有任何方法可以从字符串填充任意DOM节点,而不会遇到此类清理/验证问题?我的用例将以完全有效的结构结束(我计划稍后将其作为一个组件的子组件放置),但当我尝试构建单个组件时,浏览器阻止了我
这听起来有点像DocumentFragment应该是我正在寻找的,但据我所知,它们只能通过编程进行构造——它们不支持innerHTML
关于我为什么要这样做的一些背景:
我的用例是基于javascript的实时模板(即不输出html字符串,而是实际的DOM节点)。因此,要求如下:
- 模板输入必须允许是任意HTML(这就是为什么我使用innerHTML而不是以编程方式构造节点)
- 必须能够创建子模板,然后将其附加到更大的文档中(这就是为什么我不能一次创建整个文档)
var row = Html("<tr></tr>");
var table = Html(["<table><thead>", row, "</thead></table>"]);
var row=Html(“”);
var table=Html([“”,row,“]);
稍后我将添加如下代码:
row.append(Html(["<td>", column.header, "</td>"]));
row.append(Html([“”,column.header,“]);
以实际填充列。因此,当它被完全构造时,html将是有效的。但在中间阶段,每个模板/片段都是在单个元素下构建的。这意味着模板如下:
Html(["Hello <span>", name, "</span>"]);
Html([“你好”,名字,”]);
仍然显示为单个节点(以便它们可以作为单个实体进行操作):
你好,鲍勃
当模板在
中只产生一个子节点时,外部节点将被删除。但是在构建过程中,上面的行
模板应该看起来像
。由于我在使用innerHTML时看到的验证行为,它的结果就是
我已经检查了firefox和chrome中的所有代码都是相同的,所以我不认为我只是遇到了浏览器错误。不幸的是,你的一般问题的答案是否定的,没有办法使用
innerHTML
添加任意不完整的HTML片段。我知道这不是你想听的答案,但事实就是这样
关于innerHTML
最容易被误解的一点源于API的设计方式。它重载+
和=
运算符以执行DOM插入。这使程序员误以为它只是在执行字符串操作,而实际上innerHTML
的行为更像是一个函数而不是一个变量。如果innerHTML
是这样设计的,人们就不会那么困惑了:
element.innerHTML('some <b>html</b> here');
element.innerHTML('somehtml here');
不幸的是,现在更改API为时已晚,因此我们必须理解它实际上是一个API,而不仅仅是一个属性/变量
现在,了解innerHTML
的所谓“验证”行为。当您修改innerHTML
时,它会触发对浏览器HTML编译器的调用。它与编译html文件/文档的编译器相同。调用innerHTML
的HTML编译器没有什么特别之处。因此,无论您对html文件做什么,都可以传递到innerHTML
(一个例外是嵌入式javascript无法执行,可能是出于安全原因)
从浏览器开发人员的角度来看,这是有意义的。为什么在浏览器中包含两个单独的HTML编译器?特别是考虑到HTML编译器是巨大而复杂的野兽这一事实
缺点是,不完整的HTML将以与HTML文档相同的方式处理。如果
元素不在一个表中,大多数浏览器都会将其删除(正如您自己所观察到的)。这基本上就是您要做的——创建无效/不完整的HTML
有两种解决方法:
插入表格字符串,然后innerHTML
将整个表格重新插入页面
或
(或
),则提取HTML元素并使用DOM方法插入它不幸的是,两者都很痛苦。Mihai Stancu对jquery的评论让我想:如果你调用
$(“”)
,jquery肯定能处理这个问题。我知道jquery有一个字符串的快捷方式,看起来像单个标记,但它也必须适用于复杂的HTML
因此,我深入研究了jquery源代码,只找到了问题:
它使用一个正则表达式来检测字符串中第一个标记的名称,然后使用这个信息来确定它需要什么“上下文”
element.innerHTML('some <b>html</b> here');