【问题标题】:Alternative for innerHTML?innerHTML 的替代品?
【发布时间】:2010-10-17 14:44:32
【问题描述】:

编辑:哇。这个问题现在已经 12 岁了。

正如有人所说,自 2016 年以来可以使用单线完成:https://stackoverflow.com/a/69322509/80907


原文:

我想知道是否有一种方法可以在不使用 innerHTML 的情况下更改 HTML 中任何内容的文本。

我问的原因是因为它有点被 W3C 反对。 我知道这是吹毛求疵,但我只想知道,有没有办法?

编辑:人们似乎误解了我在这里的要求:我想找到一种方法来有效地更改正在显示的文本。

如果我有:

<div id="one">One</a>

innerHTML 允许我这样做:

var text = document.getElementsById("one");
text.innerHTML = "Two";

我屏幕上的文字也会改变。
我不想追加更多的文字,我想改变所有已经存在的文字。

【问题讨论】:

  • 仅供参考:与使用 DOM createElement、createTextNode 等相比,innerHTML 速度极快。效率考虑:quirksmode.org/dom/innerhtml.html 此外,innerHTML 是 HTML5 的一部分!
  • @Marco 你说 innerHTML 是 HTML5 的一部分是什么意思?
  • @Pacerier:innerHTML 适用于所有浏览器,但它不是 W3C HTML4.1 标准的一部分(WebDevHobo 表示对此不赞成)。而 innerHTML 应该是 HTML5 的一部分:w3.org/TR/2011/WD-html5-diff-20110113/#htmldocument-extensions
  • 可能是因为它是 .innerHTML 而不是 .innerHtml,Javascript(与 PHP 不同)是一种区分大小写的语言。
  • @Chechulin ericvasilik.com/2006/07/code-karma.html(TL;DR:当他们发明 innerHTML 时,他们无法让它在表格上工作,所以他们在表格上将其设为只读。这仅在 IE9 中得到修复。文章由 innerHTML 的发明者所著。)

标签: javascript w3c innerhtml


【解决方案1】:

推荐的方法是通过 DOM 操作,但它可能非常冗长。例如:

// <p>Hello, <b>World</b>!</p>
var para = document.createElement('p');
para.appendChild(document.createTextNode('Hello, '));

// <b>
var b = document.createElement('b');
b.appendChild(document.createTextNode('World');
para.appendChild(b);

para.appendChild(document.createTextNode('!'));

// Do something with the para element, add it to the document, etc.

编辑

响应您的编辑,为了替换当前内容,您只需删除现有内容,然后使用上面的代码填充新内容。例如:

var someDiv = document.getElementById('someID');
var children = someDiv.childNodes;
for(var i = 0; i < children.length; i++)
    someDiv.removeChild(children[i]);

但正如其他人所说,我建议改用 jQuery 之类的东西,因为并非所有浏览器都完全支持 DOM,而且那些确实存在由 JavaScript 库在内部处理的怪癖的浏览器。例如,jQuery 看起来像这样:

$('#someID').html("<p>Hello, <b>World</b>!</p>");

【讨论】:

  • 所以实际上,首先放置新文本,然后删除旧文本......这似乎是一种非常冗长的做事方式......我想知道为什么 W3C 不批准 innerHTML
  • 其他方式:) 他们的观点是,使用innerHTML,可以将无效标记插入到XML/XHTML 文档中。尽管如此,他们似乎对 HTML5 改变了主意。
  • jQuery在代码中多次使用innerHTML,因此建议使用jQuery以避免使用innerHTML没有多大意义恕我直言。
  • 此外,您应该在此问题的上下文中正确检查您的“并非所有浏览器都完全支持 DOM”声明。确实有些浏览器(主要是 IE)对 DOM 的支持很差,但是,对于这个主题,方法是完全支持的。检查兼容性表:quirksmode.org/dom/w3c_core.html#creatingelementsquirksmode.org/dom/w3c_core.html#t90
  • 删除所有子节点的更好方法是while (el.firstChild) { el.removeChild(el.firstChild); } 看起来更干净,不需要额外的索引循环
【解决方案2】:

更好的方法是使用document.createTextNode。使用此函数而不是 innerHTML 的主要原因之一是所有 HTML 字符转义都会为您处理,而如果您只是设置 innerHTML,则必须自己转义字符串。

【讨论】:

  • 然而,innerHTML 似乎比 W3C DOM 方法快得多:quirksmode.org/dom/innerhtml.html.
  • 这取决于你在做什么;说一种方法更好,这是一种误导。当对大量元素执行 childNode 列表操作时,DOM 往往会变慢(趋向于 O(n²)),而 innerHTML 可以一次完成所有这些操作。但是 innerHTML 的解析/序列化步骤可能会使其他操作变慢。
【解决方案3】:

您可以通过操作 DOM 获得相同的效果。更改文本最安全的方法是删除元素的所有子节点并用新的文本节点替换它们。

var node = document.getElementById("one");

while( node.firstChild )
    node.removeChild( node.firstChild );
node.appendChild( document.createTextNode("Two") );

删除子节点会删除元素的文本内容,然后再将其替换为新文本。

大多数开发人员避免使用 innerHTML 的原因是通过 DOM 访问元素是符合标准的。

【讨论】:

    【解决方案4】:

    如果您只想更改纯文本,那么有一个更快的依赖标准的解决方案:

    document.getElementById("one").firstChild.data = "two";
    

    无论如何,请注意,innerHTML 将成为即将到来的 HTML 5 标准的一部分。

    【讨论】:

      【解决方案5】:

      简单。

      text.innerHTML = 'two' 替换为text.firstChild.nodeValue = 'two'

      【讨论】:

        【解决方案6】:

        也在寻找绕过element.innerHTML的好方法我终于找到了解决方案:

        HTMLElement.prototype.htmlContent = function(html)
        {
            var dom = new DOMParser().parseFromString('<template>'+html+'</template>', 'text/html').head;
            this.appendChild(dom.firstElementChild.content);
        }
        
        //-- document.getElementById('my-id').innerHTML = string_of_html;
        document.getElementById('my-id').htmlContent(string_of_html);
        

        另一个没有

        HTMLElement.prototype.htmlContent = function(html)
        {
            var dom = new DOMParser().parseFromString(html, 'text/html').body;
            while (dom.hasChildNodes()) this.appendChild(dom.firstChild);
        }
        

        请记住,当innerHTML“替换”内容时,此方法实际上是“添加”内容...

        这可能会有所帮助:

        HTMLElement.prototype.clearContent = function()
        {
            while (this.hasChildNodes()) this.removeChild(this.lastChild);
        }
        
        //-- document.getElementById('my-id').innerHTML = '';
        document.getElementById('my-id').clearContent();
        

        文档:https://github.com/swannty/escaping-innerHTML
        性能:https://jsperf.com/escaping-innerhtml

        【讨论】:

          【解决方案7】:
          var who=document.getElementById('one'), txt='new text';
          if(who.innerText) who.innerText=txt;
          else if(who.textContent) who.textContent= txt;
          

          这对你来说可能和 innerHTML 一样令人反感,但它具有在某些情况下(IE)工作的优点,其中 innerHTML 或 appendChild 不能,如某些表格节点、样式和脚本元素的文本以及表单的值字段

          【讨论】:

            【解决方案8】:

            insertAdjacentHTML() 是要走的路。阅读更多: Click for documentation

            【讨论】:

            • 虽然此链接可能会回答问题,但最好在此处包含一个可用的代码示例并提供链接以供参考。
            【解决方案9】:

            这是一个非常古老的问题。

            现在,情况发生了变化:

            element.innerText = "Hi There!"
            

            单线。 自 2016 年以来,每个浏览器都支持此功能。

            【讨论】:

              【解决方案10】:

              您可以按如下方式使用 DOM:

              <html>
              <body>
              <div>before</div>
              <script type="text/javascript">
              var element = document.getElementsByTagName("div")[0];
              alert(element.firstChild.nodeValue);
              element.removeChild(element.firstChild);
              element.appendChild(document.createTextNode('after'));
              alert(element.firstChild.nodeValue);
              </script>
              </body>
              

              但我认为很少有人这样做,而是使用jQueryPrototype 之类的框架或there 之外的任何其他javascript 框架。这是 jquery 示例:

              <html>
              <head>
              <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.2.6/jquery.min.js"></script>
              </head>
              <body>
              <div>before</div>
              <script type="text/javascript">
              var element = $("div");
              alert(element.text());
              element.text("after");
              alert(element.text());
              </script>
              </body>
              

              【讨论】:

                【解决方案11】:

                在我看来,CSS+HTML+JS的组合应该可以达到预期的效果:

                .myelement:before {   
                    content: attr(alt);
                } 
                
                ...
                
                <span class='myelement' alt='initial value'></span> 
                
                ...
                
                element.setAttribute('alt', 'new value'); 
                

                有谁知道这在实践中是否可行?

                【讨论】:

                  【解决方案12】:

                  如果我正确理解你的问题,这应该是一个答案。

                  var text = document.getElementById("one");
                  //text.innerHTML = "Two";
                   text.childNodes[0].nodeValue="two";
                  

                  【讨论】:

                    【解决方案13】:

                    如果我要定期更新它,我有时会发现存储对文本节点的直接引用很有帮助。我做这样的事情:

                    var dynamicText = myDiv.appendChild(document.createTextNode("the initial text"));
                    

                    然后每当我需要更新它时,我都会这样做:

                    dynamicText.nodeValue = "the updated text";
                    

                    这避免了遍历 DOM 或添加或删除任何子项。

                    【讨论】:

                      猜你喜欢
                      • 2019-06-07
                      • 2011-12-13
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 2010-10-28
                      • 1970-01-01
                      • 2010-11-08
                      相关资源
                      最近更新 更多