Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/html/72.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript Can';t使用innerHTML从HTML字符串创建某些类型的节点_Javascript_Html_Validation_Dom - Fatal编程技术网

Javascript Can';t使用innerHTML从HTML字符串创建某些类型的节点

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”);

以下javascript(在chrome控制台中运行)没有达到我的预期:

> 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而不是以编程方式构造节点)
  • 必须能够创建子模板,然后将其附加到更大的文档中(这就是为什么我不能一次创建整个文档)
第二点是我是如何遇到这个bug的。我的模板包含一个子模板

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

有两种解决方法:

  • 从页面中提取表格,然后使用字符串处理(regex et.el.)将
    插入表格字符串,然后
    innerHTML
    将整个表格重新插入页面

  • 解析插入的HTML字符串,如果发现任何
    (或
    ),则提取HTML元素并使用DOM方法插入它


  • 不幸的是,两者都很痛苦。

    Mihai Stancu对jquery的评论让我想:如果你调用
    $(“”)
    ,jquery肯定能处理这个问题。我知道jquery有一个字符串的快捷方式,看起来像单个标记,但它也必须适用于复杂的HTML

    因此,我深入研究了jquery源代码,只找到了问题:

    它使用一个正则表达式来检测字符串中第一个标记的名称,然后使用这个信息来确定它需要什么“上下文”
    element.innerHTML('some <b>html</b> here');