如何更改元素的文本而不更改其子元素?


119

我想动态更新元素的文本:

<div>
   **text to change**
   <someChild>
       text that should not change
   </someChild>
   <someChild>
       text that should not change
   </someChild>
</div>

我是jQuery的新手,因此对我而言,此任务似乎非常艰巨。有人可以指出我要使用的功能/选择器吗?

如果可能的话,我想在不为需要更改的文本添加新容器的情况下执行此操作。


7
“如果可能的话,我希望在不为需要更改的文本添加新容器的情况下做到这一点。” 真的吗?因为在那里放一个容器会容易得多。
Paul D. Waite,2010年

伙计们,我看着原来的问题,我不认为OP说,大约子元素什么...
森那维达斯

根据W3标准,div甚至不能包含文本节点(如果我记得正确的话)。应该添加诸如<p>,<h1>等的文本容器。
Mark Ba​​ijens 2010年

2
@Mark:可能在(X)HTML Strict中,但不再存在。(HTML5现在在这里。)
Paul D. Waite,2010年

@Matt Ball:在实际的html中,有span标签而不是someChild。
ika 2010年

Answers:


75

Mark使用jQuery有更好的解决方案,但是您也可以使用常规JavaScript做到这一点。

在Javascript中,该childNodes属性为您提供元素的所有子节点,包括文本节点。

因此,如果您知道要更改的文本始终是元素中的第一件事,那么请给出以下HTML:

<div id="your_div">
   **text to change**
   <p>
       text that should not change
   </p>
   <p>
       text that should not change
   </p>
</div>

您可以这样做:

var your_div = document.getElementById('your_div');

var text_to_change = your_div.childNodes[0];

text_to_change.nodeValue = 'new text';

当然,你仍然可以使用jQuery选择<div>摆在首位(即var your_div = $('your_div').get(0);)。


1
无需替换文本节点。只需更改现有的datanodeValue财产。
Tim Down

@Tim:啊,我以为一定有更简单的方法。在jQuery出现之前,从未做过很多JavaScript。干杯,我将相应地编辑答案。
Paul D. Waite,2010年

11
因此,此答案的更新实施方式是$('#yourDivId')[0].childNodes[0].nodeValue = 'New Text';
迪恩·马丁

到目前为止,最短,最简单的解决方案- stackoverflow.com/a/54365288/4769218
银Ringvee

1
“您也许也可以使用常规javascript来做到这一点”
duhaime,

64

更新2018

由于这是一个非常受欢迎的答案,因此我决定通过将textnode选择器作为插件添加到jQuery中来对其进行一些更新和美化。

在下面的代码段中,您可以看到我定义了一个新的jQuery函数,该函数将获取所有(且仅)textNodes。您也可以使用例如该first()功能链。我在文本节点上进行修剪,并检查修剪后它是否不为空,因为空格,制表符,换行等也被识别为文本节点。如果您也需要这些节点,则只需将其从jQuery函数的if语句中删除即可。

我添加了一个示例,该示例如何替换第一个文本节点以及如何替换所有文本节点。

这种方法使读取代码更容易,并且可以多次将其用于不同目的。

更新2017年(adrach)如果你喜欢的应该仍然正常工作。

作为jQuery扩展

Javascript(ES)功能


更新2017(adrach):

自发布以来,似乎发生了一些变化。这是更新版本

$("div").contents().filter(function(){ return this.nodeType == 3; }).first().replaceWith("change text");

原始答案(不适用于当前版本)

$("div").contents().filter(function(){ return this.nodeType == 3; })
.filter(':first').text("change text");

资料来源:http//api.jquery.com/contents/


啊哈!我知道某个地方会有一个聪明的jQuery函数。编写此解决方案时,唯一的问题是每个文本节点都会获得下一个文本(例如,将其包含在子元素中)。我想限制它并不难吗?
Paul D. Waite,2010年

10
我在使用时遇到了一些麻烦.filter(':first'),但是使用.first()代替对我有用。谢谢!
hollaburoo 2012年

16
这不适合我一起工作.text()(见本的jsfiddle),但不.replaceWith()的jsfiddle这里)。
magicalex 2012年

2
这对我有用,因为它是textObject = $(myNode).contents()。filter(function(){return this.nodeType == 3;})[0] $(textObject).replaceWith(“ my text” );
马格斯

任何对此感到好奇的人nodeType=3都意味着仅过滤“ TEXT”节点类型,w3schools.com
jsref / prop_node_nodetype.asp

53

见实际

标记:

$(function() {
  $('input[type=button]').one('click', function() {
    var cache = $('#parent').children();
    $('#parent').text('Altered Text').append(cache);
  });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="parent">Some text
  <div>Child1</div>
  <div>Child2</div>
  <div>Child3</div>
  <div>Child4</div>
</div>
<input type="button" value="alter text" />


6
到目前为止,我遇到的最好的解决方案。优雅而简单。
Yoav Kadosh 2013年

3
但是,这不会保留节点的顺序。例如,如果文本首先在元素的末尾,则现在将在开始。
马特

它不会保留顺序,但是在大多数情况下,您希望文本作为第一个或最后一个节点。因此,如果append()未能获得所需的结果,请在文本前面使用prepend()。
Sensei 2015年

到目前为止,最短,最简单的解决方案- stackoverflow.com/a/54365288/4769218
银Ringvee

11
<div id="divtochange">
    **text to change**
    <div>text that should not change</div>
    <div>text that should not change</div>
</div>
$(document).ready(function() {
    $("#divtochange").contents().filter(function() {
            return this.nodeType == 3;
        })
        .replaceWith("changed text");
});

这仅更改第一个textnode


9

只需将要更改的文本包装在一个跨度中,并选择一个类即可。

我不一定会回答您的问题,但是可能会回答更好的编码习惯。保持干净整洁

<div id="header">
   <span class="my-text">**text to change**</span>
   <div>
       text that should not change
   </div>
   <div>
       text that should not change
   </div>
</div>

瞧!

$('#header .mytext').text('New text here')

这是最好的解决方案!
Sleek Geek

5

对于您提到的特定情况:

<div id="foo">
   **text to change**
   <someChild>
       text that should not change
   </someChild>
   <someChild>
       text that should not change
   </someChild>
</div>

...这很简单:

var div = document.getElementById("foo");
div.firstChild.data = "New text";

您没有说明如何对此进行概括。例如,如果您想更改中第一个文本节点的文本,则<div>可以执行以下操作:

var child = div.firstChild;
while (child) {
    if (child.nodeType == 3) {
        child.data = "New text";
        break;
    }
    child = child.nextSibling;
}

2

$.fn.textPreserveChildren = function(text) {
  return this.each(function() {
    return $(this).contents().filter(function() {
      return this.nodeType == 3;
    }).first().replaceWith(text);
  })
}

setTimeout(function() {
  $('.target').textPreserveChildren('Modified');
}, 2000);
.blue {
  background: #77f;
}
.green {
  background: #7f7;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>

<div class="target blue">Outer text
  <div>Nested element</div>
</div>

<div class="target green">Another outer text
  <div>Another nested element</div>
</div>



1

这里有很多很棒的答案,但它们只能处理一个带有孩子的文本节点。就我而言,我需要在所有文本节点上进行操作,并忽略html子级,但保留顺序。

因此,如果有这样的情况:

<div id="parent"> Some text
    <div>Child1</div>
    <div>Child2</div>
    and some other text
    <div>Child3</div>
    <div>Child4</div>
    and here we are again
</div>

我们可以使用以下代码仅修改文本并保留顺序

    $('#parent').contents().filter(function() {
        return this.nodeType == Node.TEXT_NODE && this.nodeValue.trim() != '';
    }).each(function() {
    		//You can ignore the span class info I added for my particular application.
        $(this).replaceWith(this.nodeValue.replace(/(\w+)/g,"<span class='IIIclassIII$1' onclick='_mc(this)' onmouseover='_mr(this);' onmouseout='_mt(this);'>$1X</span>"));
	});
<script src="https://code.jquery.com/jquery-3.0.0.min.js"></script>
<div id="parent"> Some text
    <div>Child1</div>
    <div>Child2</div>
    and some other text
    <div>Child3</div>
    <div>Child4</div>
    and here we are again
</div>

这是它的工作原理


0

我认为您正在寻找.prependTo()。

http://api.jquery.com/prependTo/

我们还可以在页面上选择一个元素并将其插入另一个元素:

$('h2')。prependTo($('。container'));

如果以这种方式选择的元素插入到其他位置,则它将被移入目标(未克隆):

<div class="container">  
  <h2>Greetings</h2>
  <div class="inner">Hello</div>
  <div class="inner">Goodbye</div> 
</div>

但是,如果有多个目标元素,则将在第一个目标之后为每个目标创建插入元素的克隆副本。


2
我觉得不是。听起来OP正在寻找一种方法来更改文本,而不是添加新文本。
马特·鲍尔

0

简单答案:

$("div").contents().filter(function(){ 
  return this.nodeType == 3; 
})[0].nodeValue = "The text you want to replace with"

0

马克回答的问题是您也会得到空的textnode。作为jQuery插件的解决方案:

$.fn.textnodes = function () {
    return this.contents().filter(function (i,n) {
        return n.nodeType == 3 && n.textContent.trim() !== "";
    });
};

$("div").textnodes()[0] = "changed text";

0

这是一个古老的问题,但是您可以创建一个简单的函数来简化您的生活:

$.fn.toText = function(str) {
    var cache = this.children();
    this.text(str).append(cache);
}

例:

<div id="my-div">
   **text to change**
   <p>
       text that should not change
   </p>
   <p>
       text that should not change
   </p>
</div>

用法:

$("#my-div").toText("helloworld");

0

2019 vesrsion-简短&简单

document.querySelector('#your-div-id').childNodes[0].nodeValue = 'new text';

说明

document.querySelector('#your-div-id') 用于选择父项(要更改文本的元素)

.childNodes[0] 选择文本节点

.nodeValue = 'new text' 将文本节点值设置为“新文本”


这个答案可能受到迪恩·马丁的评论的启发。我已经使用多年了,因此无法确定。只是想我应该在这里发布这种可能性,因为有些人更关心它,而不是这是最佳解决方案。


2
您刚刚复制了2014年Dean Martin的评论,并声称这是您的2019解决方案。还请使用jQuery和纯Javascript的不必要组合,我认为这对于良好的可读性是不好的做法。最后,您没有提供有关解决方案工作原理的任何详细信息。它不是最复杂,但也不是这个问题,因此可能是相当新手的程序员阅读了这篇文章,他们可以使用一些额外的解释,例如,您可以通过访问数组索引从jQuery对象获得本机DOM节点。
Mark Ba​​ijens,

@MarkBaijens我想您可能是对的,Dean Martin的评论可能是几年前我得到此摘要的地方。无论如何,从那以后我一直在使用它,只是在一月份从我的个人代码存储库(我列出了有用的脚本)中复制了它。添加了更详细的说明,并删除了不必要的jQuery。
Silver Ringvee '19年

到目前为止,这是最可行的最简单的解决方案,人们应该使用它,尽管在没有赞扬Dean Martin的情况下,将其当做自己的东西并没有得到任何荣誉。我也同意Mark Ba​​ijens的观点,在这种情况下,纯Vanilla JS实现比混合jQuery和Vanilla JS更好。jQuery不仅降低了可读性,而且还提高了性能,从而提高了性能。
Miqi180

@ Miqi180-正如我上面已经说过的,这是可能的,我不记得我最初从哪里获得此解决方案。多年来,我一直在工作中使用它。在答案中添加了注释。希望它能帮助像您这样不在乎最佳解决方案的
人像
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.