'innerText'在IE中有效,但在Firefox中不可用


289

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

myElement.innerText = "foo";

但是,似乎'innerText'属性在Firefox中不起作用。是否有与Firefox相当的产品?还是可以使用更通用的跨浏览器属性?


3
应该这样做myElement.innerHTML =“ foo”;
stefita

这将用提供的值替换对象中的所有HTML。
OMG小马,

24
在这里,像jQuery这样的库通过使您能够使用标准框架来解决此类跨浏览器的不一致问题,使生活变得更轻松。
丹·迪普洛

但是如果没有HTML可以解决的话,它仍然可能适合。
亚历克斯·波罗

21
因此,告诉我们如何使用这种跨浏览器替代方法,而不仅仅是说这是可能的(这不是建设性的)。
SasQ 2012年

Answers:


249

Firefox使用兼容W3C的 textContent属性。

我猜想Safari和Opera也支持此属性。



2
@Bob截至2016年2月22日,它仍然不是。
krillgar '16

@krillgar计划于3月8日的一周发布,用于Firefox 45。它已经在当前的beta版本中,并且已经存在了一段时间。这实际上意味着您可以开始innerText仅使用进行开发的站点,并希望它会在不久的将来在所有当前浏览器以及旧版IE上正常工作(可能会有怪癖)。
鲍勃,

1
FTR:innerText完全不同textContent,而实际上是非常有用的(令人惊讶的从推测IE怪癖...):innerText试图给如何文本是一种近似实际呈现在浏览器中,全然不像textContent,这只是对返回标签-剥夺了标记源,几乎没有价值,甚至出现了其他问题(例如字边界的丢失)。
Sz。

innerText属性依然没有在2019年支持64版本
贝东

285

更新:我写了一篇博客文章,详细介绍了所有差异


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

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

只是为了让事情更有趣,歌剧院-除了执行标准textContent-决定也添加MSHTML的innerText ,但改变了它作为textContent -即包括脚本内容(事实上,textContentinnerText在Opera似乎产生相同的结果,可能是被刚刚化名为对方) 。

textContentNode接口的一部分,而是innerText的一部分HTMLElement。例如,这意味着您可以“检索” 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抽象(以解决这些缺陷),但事实证明它相当复杂

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

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


35
Chrome也支持innerText,因此Firefox似乎是唯一不支持它的主要浏览器。IE是唯一不支持textContent的浏览器。
mike nelson'2

7
@mike-但似乎innerText在Chrome中使用的速度要慢60倍。jsperf.com/text-content/3
gblazex 2011年

8
textContentIE9 +现在支持,但Firefox仍然不支持innerText(尽管它们确实添加outerHTML了几天前引入的IE )。
kangax

1
对于仍需要支持IE8的用户,此处有一个非常完善的Node.textContent填充程序:github.com/usmonster/aight/blob/node-textcontent-shim/js/…(希望很快会包含在aight中)。
2014年


83

如果您只需要设置文本内容而不需要检索,则可以使用任何浏览器上的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 2011年

23
@RexE:JavaScript确实有一个!==运算符,即的反函数======/ !==所使用的类型敏感比较通常优于松散的比较器==/ !=
bobince 2011年

在Internet Explorer中,这无法设置脚本标签的文本(我将它们用作模板)。您已设置`scriptTagElement.text ='我的模板{{here}}';
Christopher Tarquini 2012年

我不得不非常努力地理解为什么您使用了循环(我会!==null顺便丢弃整个循环),而不是仅仅用element.innerHTML=''(替换为与循环完全相同的工作)替换循环,然后我就记得了。 。:(legacy-)IE中的表格... ericvasilik.com/2006/07/code-karma.html 可能我建议添加对“隐藏”的简短描述,并且几乎从未记录过createTextNode替换amp lt的“副作用” 和gt到它们各自的html字符实体吗?链接到它的确切行为将是盛大的!
GitaarLAB


22

根据Prakash K的回答,Firefox不支持innerText属性。因此,您可以简单地测试用户代理是否支持此属性,并按照以下步骤进行操作:

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

2
elem中的“ textContent”会更简单
Jamie Pate

如果(elem.textContent!= null)也会更容易!
Elmue '16

14

一个非常简单的Java语言行可以在所有主要浏览器中获取“非杂音”文本。

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

2
有一个问题(至少在IE8中如此):如果innerText为空字符串,并且textContent未定义,则(myElement.innerText || myElement.textContent)变为不确定。
Magnus 2015年

1
除了@Magnus指出的错误外,还值得注意的事实是,对于某些用例而言,在如何textContentinnerText报告空白方面存在重大差异
Mark Amery

2
只需添加另一个||,即:var myText = (myElement.innerText || myElement.textContent || "") ;即可克服未定义的值。
PeterM 2015年

6

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

还考虑其他CSS属性:

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

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

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

然后,Chrome浏览器会同时支持这两个属性,但是它们的内容可能会有所不同。较旧的浏览器仍包含在innetText中,类似于textContent现在包含的所有内容(但它们与空白/换行符的生成有关的行为不一致)。

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

需要说明的是,此jQuery方法不会插入任何可能由内容的子元素(如<br />)引起的在屏幕上可见的多余空格或换行符。

如果您设计了一些用于辅助功能的脚本,并且您的样式表已针对非听觉渲染进行了解析,例如用于与盲文阅读器进行通信的插件,则该工具必须使用textContent,前提是该工具必须包含在使用以下样式设置的跨度中添加的特定标点符号“ display:none”并且通常包含在页面中(例如,上标/下标),否则,innerText在盲文阅读器上会非常混乱。

现在,主要的搜索引擎通常会使用HTML / CSS解析器和DOM属性,将CSS技巧隐藏的文本忽略掉(它们还会解析HTML页面的CSS,也将忽略背景上没有对比色的文本)。 “ innerText”完全类似于现代视觉浏览器(至少不可见的内容不会被索引,因此隐藏的文本不能用作强制在页面中包含某些关键字来检查其内容的技巧);但是使用“ textContent”属性而不是完整的HTML来剥离多余的样式和脚本,但此隐藏的文本将在结果页面上显示(如果该页面仍符合要包含在结果中的索引的条件)。

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


1
实际上,Chrome / WebKit包含“字体大小:0”,“颜色:透明”,“不透明度:0”,“文本缩进:-9999px”等innerText。在我的测试中,仅忽略“显示:无”和“可见性:隐藏”。
kangax

5
myElement.innerText = myElement.textContent = "foo";

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


4
-1; 这是一个坏主意。代码-包括jQuery之类的代码中的代码- 检查是否存在innerTexttextContent属性以确定要使用哪个属性,这是极为常见的。通过将两者都设置为字符串,您将使其他人对该元素进行操作的代码错误地检测到浏览器同时支持这两种属性。因此,该代码容易出现错误行为。
Mark Amery

jQuery $('#myElement')。val()适用于跨浏览器。
Tony Dong

4

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


是否有保鲜盒?
serv-inc

1
@user确实取决于您的需求。如果您不需要支持旧版本的Firefox,也不必在意实现上的细微差别,请使用innerText。如果textContent可以接受,并且需要支持旧的Fx,请使用(innerText || textContent)。如果您想在所有浏览器中实现相同的实现,则我不认为对此有任何特定的polyfill,但是某些框架(例如jQuery)可能已经实现了类似的功能-请参阅此页面上的其他答案。
鲍勃

1
的功能innerText,即:在Firefox> = 38(用于附加组件)中,页面上的可见文本至少<script>应完全省略标记。jQuery $('#body').text()不适用于我。但是作为一种解决方法innerText || textContent是可以的。谢谢。
serv-inc

@用户是的,如果您需要支持Fx 38,则此答案实际上并不适用。您现在必须忍受的限制/差异textContent
鲍勃

1

那这样的东西呢?

//$elem is the jQuery object passed along.

var $currentText = $elem.context.firstChild.data.toUpperCase();

**我需要将我的字母大写。


1
废液;如果该元素包含的内容超出单个文本节点,则此方法将无效。
Mark Amery

1

与2016年的Firefox v45一样,innerText可在firefox上运行,请查看其支持:http : //caniuse.com/#search=innerText

如果您希望它在Firefox的早期版本上运行textContent,则可以使用,它在Firefox上具有更好的支持,而在较旧的IE版本上则更差http : //caniuse.com/#search=textContent


0

这一直是我的经验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

即= Internet Explorer,ff = Firefox,ch =谷歌浏览器。注1:ff起作用,直到用退格键删除值之后-参见上面的Ray Vega的注释。注意2:在chrome中可以使用-更新后它保持不变,然后单击鼠标左键,然后单击返回到该字段,然后显示该值。最好的是elem.value = changeVal; 我在上面没有评论。


1
只有我吗 ?还是绝对忽略OP问题?他要求提供innerText / textContent,而您主要是在谈论输入。
Dementic 2012年

这个答案很难读。另一方面,我不认为内容具有足够的价值以值得整理。
Mark Amery

-1

只需从原始帖子下的评论中重新发布即可。innerHTML在所有浏览器中均可使用。谢谢stefita。

myElement.innerHTML =“ foo”;


1
-1; innerHTML不能完全替代textContent/,innerText除非可以确定要分配的文本不包含任何标签或其他HTML语法。对于用户提供的任何数据,您绝对没有保证。鉴于这种警告可能会导致XSS安全漏洞,因此在没有这种警告的情况下推广这种方法是很危险的。有了这么多安全的方法,甚至没有理由考虑这一点。
Mark Amery

马克,我的理解是,innerHTML是将数据写入div,span,p等html元素的正常方法。我用它来处理返回的JSON数据。它也在JQuery中...
Leonid Alzhin

1
如果您从JSON响应中获得一个任意字符串,并将其分配给一个元素.innerHTML,则您的代码将被破坏,并且很可能会受到XSS的攻击。如果该字符串是"<script>alert(1)</script>"怎么办?
Mark Amery

1
@MarkAmery:HTML5指定不应执行<script>通过插入的标签innerHTML。但这并不能保护较旧的浏览器。另外,HTML5 innerHTML不会保护例如"<img src='x' onerror='alert(1)'>"
GitaarLAB

-1

在这里找到这个:

<!--[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 本机支持textContent时,为什么使用条件注释将执行限制为IE> = 8,而不是仅针对IE 8 ?另外值得一提的是,由于innerTexttextContent具有不同的行为,上面的代码是不是忠实的textContent垫片-这是潜在的重要,但不一定有明显的!
Mark Amery

感谢您指出漏洞,该漏洞的目标是IE <= 8
simonarame

-2

也可以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");
         }
     });
 }

只是想在我的头上寻找问题,setter被破坏了,pre因为它会使换行符加倍。我怀疑这里还有更多错误。
Mark Amery
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.