【问题标题】:'innerText' works in IE, but not in Firefox'innerText' 在 IE 中有效,但在 Firefox 中无效
【发布时间】:2010-11-24 11:21:40
【问题描述】:

我有一些可在 IE 中运行的 JavaScript 代码,其中包含以下内容:

myElement.innerText = "foo";

但是,'innerText' 属性似乎在 Firefox 中不起作用。有一些 Firefox 等价物吗?还是可以使用更通用的跨浏览器属性?

【问题讨论】:

  • 应该这样做 myElement.innerHTML = "foo";
  • 这将用提供的值替换对象中的所有 HTML。
  • 这是 jQuery 之类的库让生活变得更轻松的地方,因为它们通过使您能够使用标准框架来处理此类跨浏览器的不一致问题。
  • 但如果没有 HTML 需要处理,仍然可能适合。
  • 所以告诉我们如何使用这个跨浏览器的替代方案,而不是仅仅说它是可能的(这不是建设性的)。

标签: javascript internet-explorer firefox cross-browser


【解决方案1】:

更新:我写的blog post detailing all the differences好多了。


Firefox 使用 W3C 标准 Node::textContent,但其行为与 MSHTML 专有的 innerText 的行为“略有不同”(不久前,Opera 也复制了许多其他 MSHTML 功能)。

首先,textContent 空白表示不同于innerText 的表示。其次,更重要的是,textContent 包含所有 SCRIPT 标签内容,而 innerText 不包含。

为了让事情更有趣,Opera - 除了实现标准 textContent - 决定还添加 MSHTML 的 innerText 但将其更改为 textContent - 即包括 SCRIPT 内容(在事实上,Opera 中的textContentinnerText 似乎产生了相同的结果,可能只是彼此有别名)。

textContentNode 接口的一部分,而innerTextHTMLElement 的一部分。例如,这意味着您可以从文本节点“检索”textContent,但不能“检索”innerText

var el = document.createElement('p');
var textNode = document.createTextNode('x');

el.textContent; // ""
el.innerText; // ""

textNode.textContent; // "x"
textNode.innerText; // undefined

最后,Safari 2.x 也有错误的innerText 实现。在 Safari 中,innerText 仅在元素为 既不是隐藏的(通过style.display == "none")也不是文档中的孤儿。否则,innerText 会产生一个空字符串。

我在玩textContent 抽象(解决这些缺陷),但结果是rather complex

最好的办法是首先定义您的确切要求,然后从那里开始。通常可以简单地从元素的innerHTML 中剥离标签,而不是处理所有可能的textContent/innerText 偏差。

当然,另一种可能性是遍历 DOM 树并递归收集文本节点。

【讨论】:

【解决方案2】:

Firefox 使用 W3C-compliant textContent 属性。

我猜 Safari 和 Opera 也支持这个属性。

【讨论】:

  • @Bob 截至 2016 年 2 月 22 日,它仍然不是。
  • @krillgar 它计划用于 Firefox 45,将于 3 月 8 日当周发布。它已经在当前的 beta 版本中,并且在极光中已经有一段时间了。这实际上意味着您可以开始仅使用 innerText 开发网站,并期望它在不久的将来在所有当前浏览器以及旧 IE 上都能正常工作(可能会有一些怪癖)。
  • FTR: innerText 是来自 textContentprofoundly different,实际上非常有用(令人惊讶的是来自一个假定的 IE 怪癖......):innerText 试图给出一个近似值文本在浏览器中实际呈现,与textContent 完全不同,textContent 返回的只是标签剥离的标记源,几乎没有添加任何价值,甚至是额外的问题(例如单词边界的丢失)。
  • innerText 在 2019 年版本 64 上仍然不支持。
【解决方案3】:

如果您只需要设置文本内容而不需要检索,这里有一个简单的 DOM 版本,您可以在任何浏览器上使用;它不需要 IE innerText 扩展或 DOM Level 3 Core textContent 属性。

function setTextContent(element, text) {
    while (element.firstChild!==null)
        element.removeChild(element.firstChild); // remove all existing content
    element.appendChild(document.createTextNode(text));
}

【讨论】:

  • 除非 JavaScript 有 "!==" 运算符,否则我认为第二行中的运算符应该只是 "!="。
  • @RexE:JavaScript 确实有一个!== 运算符,是=== 的倒数。 ===/!== 使用的类型敏感比较通常优于松散比较器 ==/!=
  • 在 Internet Explorer 中,设置脚本标签的文本不起作用(我将它们用作模板)。您已设置 `scriptTagElement.text = 'my template {{here}}';
  • 我不得不认为 非常 很难理解你为什么使用循环(顺便说一下,我会完全放弃 !==null)而不是仅仅用 @ 替换循环987654330@(它被指定做与循环完全相同的工作,然后我记得......:(旧版-)IE中的表格......ericvasilik.com/2006/07/code-karma.html我可能建议添加“隐藏”的简短描述并且几乎从未记录了 createTextNode 将 amp lt 和 gt 替换为各自的 html 字符实体的“副作用”?指向它的确切行为的链接会很棒!
【解决方案4】:

jQuery 提供了一个.text() 方法,可以在任何浏览器中使用。例如:

$('#myElement').text("Foo");

【讨论】:

    【解决方案5】:

    根据 Prakash K 的回答,Firefox 不支持 innerText 属性。所以你可以简单地测试一下用户代理是否支持这个属性,然后进行如下操作:

    function changeText(elem, changeVal) {
        if (typeof elem.textContent !== "undefined") {
            elem.textContent = changeVal;
        } else {
            elem.innerText = changeVal;
        }
    }
    

    【讨论】:

    • 'textContent' in elem 会更简单
    • if (elem.textContent != null) 也会更简单!
    【解决方案6】:

    一行非常简单的 Javascript 就可以在所有主流浏览器中获取“非标记”文本...

    var myElement = document.getElementById('anyElementId');
    var myText = (myElement.innerText || myElement.textContent);
    

    【讨论】:

    • 那个有问题(至少在 IE8 中):如果 innerText 是空字符串且 textContent 未定义,则 (myElement.innerText || myElement.textContent) 变为未定义。
    • 除了@Magnus 指出的错误之外,还值得一提的是significant differences in how textContent and innerText report whitespace 对于某些用例可能很重要。
    • 只需添加另一个||,即:var myText = (myElement.innerText || myElement.textContent || "") ; 即可克服未定义的值。
    【解决方案7】:

    请注意,Element::innerText 属性将包含在 Google Chrome 中被 CSS 样式“display:none”隐藏的文本(同时它会丢弃已被其他 CSS 技术(包括 font-size:0、color:transparent 和其他一些导致文本不以任何可见方式呈现的类似效果)。

    还考虑了其​​他 CSS 属性:

    • 首先解析内部元素的“display:”样式以确定它是否分隔块内容(例如“display:block”,这是浏览器内置样式表中 HTML 块元素的默认设置,其行为不是被您自己的 CSS 样式覆盖);如果是这样,将在 innerText 属性的值中插入一个换行符。 textContent 属性不会发生这种情况。
    • 还会考虑生成内联内容的 CSS 属性:例如,生成内联换行符的内联元素 <br \> 也会在 innerText 的值中生成一个换行符。
    • “display:inline”样式不会导致 textContent 或 innerText 中的换行符。
    • “display:table”样式会在表格周围和表格行之间生成换行符,但“display:table-cell”会生成制表符。
    • “position:absolute”属性(与 display:block 或 display:inline 一起使用,没关系)也会导致插入换行符。
    • 某些浏览器还会在跨度之间包含一个空格分隔

    Element::textContent 仍将包含独立于应用的 CSS 的内部文本元素的所有内容,即使它们是不可见的。并且 textContent 中不会生成额外的换行符或空格,它只会忽略所有样式以及内部元素的结构和内联/块或定位类型。

    使用鼠标选择的复制/粘贴操作将丢弃以纯文本格式放入剪贴板的隐藏文本,因此它不会包含textContent 中的所有内容,而只会包含innerText 中的内容(如上所述在生成空格/换行符之后)。

    这两个属性在 Google Chrome 中都受支持,但它们的内容可能会有所不同。较旧的浏览器仍然包含在 innetText 中的所有内容,例如 textContent 现在包含的内容(但它们与当时生成的空格/换行符相关的行为不一致)。

    jQuery 将使用“.text()”方法解决浏览器之间的这些不一致问题,该方法添加到它通过 $() 查询返回的已解析元素中。在内部,它通过查看 HTML DOM 解决了困难,仅使用“节点”级别。所以它会返回一些看起来更像标准 textContent 的东西。

    需要注意的是,这个 jQuery 方法不会插入由内容的子元素(如 <br />)引起的屏幕上可能可见的任何额外空格或换行符。

    如果您为可访问性设计了一些脚本,并且您的样式表被解析为非听觉呈现,例如用于与盲文阅读器通信的插件,则此工具应使用 textContent 如果它必须包含添加的特定标点符号spans 样式为“display:none”,通常包含在页面中(例如上标/下标),否则 innerText 在盲文阅读器上会非常混乱。

    使用 HTML/CSS 解析器和DOM 属性 "innerText" 与现代视觉浏览器中的完全一样(至少这种不可见的内容不会被索引,因此隐藏的文本不能用作强制在页面中包含某些关键字以检查其内容的技巧);但是这个隐藏的文本仍然会显示在结果页面中(如果页面仍然符合索引以包含在结果中),使用“textContent”属性而不是完整的 HTML 来去除额外的样式和脚本。

    如果您在这两个属性中的任何一个中分配了一些纯文本,这将覆盖应用到它的内部标记和样式(只有分配的元素会保留其类型、属性和样式),因此两个属性都将包含相同的内容。但是,一些浏览器现在将不再支持对 innerText 的写入,并且只会让您覆盖 textContent 属性(在写入这些属性时,您不能插入 HTML 标记,因为 HTML 特殊字符将使用数字字符引用正确编码以按字面意思显示,如果您在分配innerTexttextContent 之后读取innerHTML 属性。

    【讨论】:

    • 其实Chrome/WebKit的innerText中都包含了“font-size: 0”、“color: transparent”、“opacity: 0”、“text-indent: -9999px”等.在我的测试中,只有“显示:无”和“可见性:隐藏”被忽略。
    【解决方案8】:
    myElement.innerText = myElement.textContent = "foo";
    

    编辑(感谢 Mark Amery 在下面的评论):只有在您毫无疑问地知道没有代码会依赖检查这些属性的存在时才这样做,例如(例如)jQuery 确实.但是,如果您使用的是 jQuery,您可能只使用“文本”函数并执行 $('#myElement').text('foo') ,正如其他一些答案所示。

    【讨论】:

    • -1;这是一个坏主意。代码(包括code in libraries like jQuery)检查innerTexttextContent 属性的存在以决定使用哪一个是非常常见的。通过将两者都设置为字符串,您将使其他人的代码作用于元素错误地检测到浏览器支持这两个属性;因此,该代码很容易行为不端。
    • JQuery $('#myElement').val() 适用于跨浏览器。
    【解决方案9】:

    innerText 已添加到 Firefox,应该在 FF45 版本中可用:https://bugzilla.mozilla.org/show_bug.cgi?id=264412

    已经编写了一个草案规范,预计将来会纳入 HTML 生活标准:http://rocallahan.github.io/innerText-spec/https://github.com/whatwg/html/issues/465

    请注意,目前 Firefox、Chrome 和 IE 的实现都是不兼容的。展望未来,我们可能会期待 Firefox、Chrome 和 Edge 融合,而旧的 IE 仍然不兼容。

    另请参阅:https://github.com/whatwg/compat/issues/5

    【讨论】:

    • 有可用的 polyfill 吗?
    • @user 这真的取决于你需要什么。如果您不需要支持旧版本的 Firefox 并且不关心实现上的细微差别,只需使用 innerText。如果textContent 是可接受的后备方案并且您需要支持旧的 Fx,则使用(innerText || textContent)。如果您想在所有浏览器中实现相同的实现,我不相信有任何特定的 polyfill 用于此,但某些框架(例如 jQuery)可能已经实现了类似的东西 - 请参阅此页面上的其他答案。
    • innerText 的功能,即:页面上的可见文本,在 Firefox >= 38(对于插件)至少,<script> 标签应该完全省略。 jQuery 的$('#body').text() 对我不起作用。但作为一种解决方法innerText || textContent 是可以的。谢谢。
    • @user 是的,如果您需要支持 Fx 38,那么这个答案并不适用。你现在必须忍受textContent 的限制/差异。
    【解决方案10】:

    这是我对innerTexttextContentinnerHTML 和值的体验:

    // elem.innerText = changeVal;  // works on ie but not on ff or ch
    // elem.setAttribute("innerText", changeVal); // works on ie but not ff or ch
    // elem.textContent = changeVal;  // works on ie but not ff or ch
    // elem.setAttribute("textContent", changeVal);  // does not work on ie ff or ch
    // elem.innerHTML = changeVal;  // ie causes error - doesn't work in ff or ch
    // elem.setAttribute("innerHTML", changeVal); //ie causes error doesn't work in ff or ch
       elem.value = changeVal; // works in ie and ff -- see note 2 on ch
    // elem.setAttribute("value", changeVal); // ie works; see note 1 on ff and note 2 on ch
    

    ie = Internet Explorer,ff = firefox,ch = google chrome。 注意 1: ff 一直有效,直到使用退格键删除值 - 请参阅上面 Ray Vega 的注释。 注意 2:在 chrome 中有点工作 - 更新后它没有改变,然后你点击离开并点击回到该字段并出现值。 最好的是elem.value = changeVal;我没有在上面评论。

    【讨论】:

    • 只有我一个人吗?还是完全忽略 OP 问题?他要求innerText/textContent,而您主要是在谈论输入。
    • 这个答案很难阅读。另一方面,我不相信内容有足够的价值值得整理。
    【解决方案11】:

    与 2016 年的 Firefox v45 一样,innerText 在 Firefox 上工作,看看它的支持:http://caniuse.com/#search=innerText

    如果你想让它在以前版本的 Firefox 上工作,你可以使用textContent,它对 Firefox 的支持更好,但对旧 IE 版本的支持更差http://caniuse.com/#search=textContent

    【讨论】:

      【解决方案12】:

      这样的事情呢?

      //$elem is the jQuery object passed along.
      
      var $currentText = $elem.context.firstChild.data.toUpperCase();
      

      ** 我需要把我的大写。

      【讨论】:

      • 废话解决方案;如果元素包含的不仅仅是一个文本节点,这将不起作用。
      【解决方案13】:

      只是在原帖下从 cmets 转发。 innerHTML 适用于所有浏览器。谢谢stefita。

      myElement.innerHTML = "foo";

      【讨论】:

      • -1; innerHTML 不能充分替代 textContent/innerText,除非您可以确定您分配的文本不包含任何标签或其他 HTML 语法。对于用户提供的任何数据,你肯定没有那个保证。在没有警告的情况下推动这种方法是危险的,因为它可能导致XSS 安全漏洞。有这么多安全的方法可用,甚至没有理由考虑这个。
      • 马克,我的理解是,innerHTML 是一种将数据写入 div、span、p 等 html 元素的正常方式。我用它来处理返回的 JSON 数据。它也在 JQuery 中......
      • 如果您从 JSON 响应中获取任意字符串并将其分配给元素的 .innerHTML,则您的代码已损坏并且您可能容易受到 XSS 攻击。如果该字符串是"<script>alert(1)</script>",会发生什么?
      • @MarkAmery:HTML5 指定不应执行通过innerHTML 插入的<script> 标记。但这并不能保护旧版浏览器。此外,HTML5 innerHTML 不会保护例如 "<img src='x' onerror='alert(1)'>"
      【解决方案14】:

      在这里找到这个:

      <!--[if lte IE 8]>
          <script type="text/javascript">
              if (Object.defineProperty && Object.getOwnPropertyDescriptor &&
                  !Object.getOwnPropertyDescriptor(Element.prototype, "textContent").get)
                (function() {
                  var innerText = Object.getOwnPropertyDescriptor(Element.prototype, "innerText");
                  Object.defineProperty(Element.prototype, "textContent",
                    { // It won't work if you just drop in innerText.get
                      // and innerText.set or the whole descriptor.
                      get : function() {
                        return innerText.get.call(this)
                      },
                      set : function(x) {
                        return innerText.set.call(this, x)
                      }
                    }
                  );
                })();
          </script>
      <![endif]-->
      

      【讨论】:

      • 一些解释会很好!另外,这里有一些奇怪的东西;当 IE >= 9 support textContent natively 时,为什么要使用条件注释将执行限制为 IE >= 8,而不是仅针对 IE 8?还值得注意的是,由于 innerTexttextContent 具有不同的行为,上面的代码不是忠实的 textContent shim - 这可能很重要,但不一定很明显!
      • 感谢指出漏洞,它的目标是IE
      【解决方案15】:

      也可以在其他浏览器中模拟innerText 行为:

       if (((typeof window.HTMLElement) !== "undefined") && ((typeof HTMLElement.prototype.__defineGetter__) !== "undefined")) {
           HTMLElement.prototype.__defineGetter__("innerText", function () {
               if (this.textContent) {
                   return this.textContent;
               } else {
                   var r = this.ownerDocument.createRange();
                   r.selectNodeContents(this);
                   return r.toString();
               }
           });
           HTMLElement.prototype.__defineSetter__("innerText", function (str) {
               if (this.textContent) {
                   this.textContent = str;
               } else {
                   this.innerHTML = str.replace(/&/g, '&amp;').replace(/>/g, '&gt;').replace(/</g, '&lt;').replace(/\n/g, "<br />\n");
               }
           });
       }
      

      【讨论】:

      • 只是在寻找我头脑中的问题,pres 的设置器坏了,因为它会使换行符加倍。我怀疑这里还有更多错误。
      猜你喜欢
      • 2011-02-18
      • 2011-01-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-04-01
      • 2011-12-17
      • 1970-01-01
      相关资源
      最近更新 更多