9

我编写了一些 JavaScript 来允许编辑 HTML 表单中的项目列表,包括添加和删除项目。让它在 Firefox 中工作。在 Internet Explorer 中尝试时,我发现任何添加的项目都没有与表单一起提交。

长话短说...大量的简化、调试,找出了触发 IE 忽略新表单输入的行。这样行为问题就解决了。

但现在我必须问:为什么?这是一个IE错误吗?

这是简化的代码:

<html>
<head>
    <title>Test</title>
    <script type="text/javascript">
        function add() {
            div = document.getElementById("mylist");

            // *** Adding text here works perfectly fine. ***
            div.innerHTML += " ";

            e = document.createElement("input");
            e.setAttribute("type", "text");
            e.setAttribute("name", "field3");
            e.setAttribute("value", "--NEWVALUE--");
            div.appendChild(e);

            // *** Adding text here works perfectly fine in Firefox, but for
            //     Internet Explorer it causes field3 to not be submitted. ***
            //div.innerHTML += " ";
        }
    </script>
</head>
<body>
    <form action="" method="get">
        <div id="mylist">
            <input type="text" name="field1" value="value1" />
            <input type="text" name="field2" value="value2" />
        </div>
        <a href="javascript:" onclick="add()" />Add</a>
        <input type="submit" value="Submit" />
    </form>
</body>
</html>

要尝试一下,做显而易见的事情:在 IE 中加载,单击添加,单击提交,查看地址栏中的内容。如果你取消最后一行的注释add(),IE 会突然停止报告field3。无论哪种方式,它在 Firefox 中都可以正常工作。

有任何想法吗?好奇的心想知道。(如果需要,我将如何以便携的方式在其中添加文本,让 IE 很高兴?)

4

3 回答 3

7

这是一个IE错误吗?

似乎如此。当您通过 DOM 方法创建 <input> 元素时,IE 并没有完全拾取 'name' 属性。元素确实提交了,但如果您尝试获取元素的“innerHTML”表示,它就会神秘地消失。如果您通过直接写入innerHTML 创建元素,则不会发生这种情况。

此外,如果您使用 DOM 级别 0 表单导航方法,例如“myform.elements.x.value”,则通过“元素”数组访问可能不起作用(类似于某些人错误使用的直接“myform.x”访问)。无论如何,这些天您可能更喜欢 getElementById()。

所以要么使用innerHTML ,要么使用DOM方法;创建表单域时最好不要混合它们。

这已记录在案(请参阅“备注”)并最终在 IE8 中修复。

在任何情况下,永远不要这样做:

div.innerHTML+= '...';

这只是语法糖:

div.innerHTML= div.innerHTML+'...';

换句话说,它必须序列化元素的整个子 HTML 内容,然后进行字符串连接,然后将新字符串重新解析回元素,丢弃所有原始内容。这意味着您将丢失任何无法序列化的内容:以及 IE 的虚假半创建“名称”属性,这也意味着您附加到每个子元素的任何 JavaScript 事件处理程序、DOM 侦听器或其他自定义属性。此外,不必要的序列化/解析周期很慢。

于 2009-03-04T19:36:13.670 回答
3

IE 对在运行时更改一些内置属性非常挑剔。例如,输入元素的名称在设置时不能更改。

如果我是你,我会尝试两件事:

  1. setAttribute()尝试显式设置和属性name,而不是使用:typevalue

    e.name = "text";

  2. 如果这不起作用,您可能必须在document.createElement()调用中包含所有这些属性:

    var e = document.createElement("<input type='text' name='field'>");

    这实际上可能会在某些浏览器中引发异常。所以最好的跨浏览器方法是:

.

var e;
  try {
    e = document.createElement("<input type='text' name='field'>");
  } catch (ex) {
    e = document.createElement("input");
    e.type = 'text';
    e.name = 'field';
  }
  e.value = 'value';
于 2009-03-04T19:02:59.787 回答
3

谢谢 bobince 和 levik 的回答。使用这些以及更多的实验,这是我的结论:

  1. 是的,这是一个 IE 错误。

  2. IE 8 根据微软的说法修复了该错误:“Internet Explorer 8 及更高版本可以在运行时对使用 createElement 方法动态创建的元素设置 NAME 属性。”

  3. e.setAttribute("name", "field3")错误是这样的:仅调用kind-of 会设置名称。如果元素没有发生任何其他事情,它将起作用,但如果请求序列化,则不会序列化名称。所以当我说innerHTML += " "强制序列化时,它失去了名字,所以它在反序列化时没有恢复。没有名字,没有包含在表单提交中。

  4. 解决方法 #1:e = document.createElement("<input name='field3' />")即使在面临序列化时也可以。

  5. 解决方法 #2:我可以附加一个像这样的文本元素,而不是使用 innerHTML += 添加文本div.appendChild(document.createTextNode(" "));:我认为必须有更好的添加文本的方法,现在我知道了:-)。

干杯,
--jsf

于 2009-03-04T20:26:41.117 回答