简体   繁体   English

如何在不更改元素的子元素的情况下更改元素的文本?

[英]How can I change an element's text without changing its child elements?

I'd like to update element's text dynamically:我想动态更新元素的文本:

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

I'm new to jQuery, so this task seems to be quite challenging for me.我是 jQuery 的新手,所以这个任务对我来说似乎很有挑战性。 Could someone point me to a function/selector to use?有人可以指出我要使用的功能/选择器吗?

If it is possible, I'd like to do it without adding a new container for the text I need to change.如果可能的话,我想在不为需要更改的文本添加新容器的情况下执行此操作。

Mark's got a better solution using jQuery , but you might be able to do this in regular JavaScript too. Mark 使用 jQuery 获得了更好的解决方案,但您也可以在常规 JavaScript 中执行此操作。

In Javascript, the childNodes property gives you all the child nodes of an element, including text nodes.在 Javascript 中, childNodes属性为您提供元素的所有子节点,包括文本节点。

So, if you knew the text you wanted to change was always going to be the first thing in the element, then given eg this HTML:因此,如果您知道要更改的文本始终是元素中的第一件事,那么给定例如以下 HTML:

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

You could do this:你可以这样做:

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

var text_to_change = your_div.childNodes[0];

text_to_change.nodeValue = 'new text';

Of course, you can still use jQuery to select the <div> in the first place (ie var your_div = $('your_div').get(0); ).当然,您仍然可以使用 jQuery 首先选择<div> (即var your_div = $('your_div').get(0); )。

Update 2018 2018 年更新

Since this is a pretty popular answer I decided to update and beautify it a little by adding the textnode selector to jQuery as a plugin.由于这是一个非常受欢迎的答案,我决定通过将 textnode 选择器作为插件添加到 jQuery 来更新和美化它。

In the snippet below you can see that I define a new jQuery function that gets all (and only) the textNodes.在下面的代码片段中,您可以看到我定义了一个新的 jQuery 函数,该函数获取所有(且仅)textNode。 You can chain of this function as well with for example the first() function.您也可以将此函数与例如first()函数链接起来。 I do a trim on the text node and check if it's not empty after the trim because spaces, tabs, new lines, etc. are also recognized as text nodes.我对文本节点进行修剪并检查修剪后它是否不为空,因为空格、制表符、新行等也被识别为文本节点。 If you need those nodes too then simple remove that from the if statement in the jQuery function.如果你也需要这些节点,那么简单地从 jQuery 函数的 if 语句中删除它。

I added an example how to replace first text node and how to replace all text nodes.我添加了一个如何替换第一个文本节点以及如何替换所有文本节点的示例。

This approach makes it easier to read the code and easier to use it multiple times and with different purposes.这种方法使代码更容易阅读,并且更容易多次使用并用于不同的目的。

The Update 2017 (adrach) should still work as well if you prefer that.如果您愿意, 2017 年更新 (adrach)应该仍然有效。

As jQuery extension作为 jQuery 扩展

 //Add a jQuery extension so it can be used on any jQuery object jQuery.fn.textNodes = function() { return this.contents().filter(function() { return (this.nodeType === Node.TEXT_NODE && this.nodeValue.trim() !== ""); }); } //Use the jQuery extension $(document).ready(function(){ $('#replaceAll').on('click', () => { $('#testSubject').textNodes().replaceWith('Replaced'); }); $('#replaceFirst').on('click', () => { $('#testSubject').textNodes().first().replaceWith('Replaced First'); }); });
 p { margin: 0px; }
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <div id="testSubject"> **text to change** <p>text that should not change</p> <p>text that should not change</p> **also text to change** <p>text that should not change</p> <p>text that should not change</p> **last text to change** </div> <button id="replaceFirst">Replace First</button> <button id="replaceAll">Replace All</button>

Javascript (ES) eqivilant Javascript (ES) 等效

 //Add a new function to the HTMLElement object so it cna be used on any HTMLElement HTMLElement.prototype.textNodes = function() { return [...this.childNodes].filter((node) => { return (node.nodeType === Node.TEXT_NODE && node.nodeValue.trim() !== ""); }); } //Use the new HTMLElement function document.addEventListener('DOMContentLoaded', () => { document.querySelector('#replaceAll').addEventListener('click', () => { document.querySelector('#testSubject').textNodes().forEach((node) => { node.textContent = 'Replaced'; }); }); document.querySelector('#replaceFirst').addEventListener('click', function() { document.querySelector('#testSubject').textNodes()[0].textContent = 'Replaced First'; }); });
 p { margin: 0px; }
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <div id="testSubject"> **text to change** <p>text that should not change</p> <p>text that should not change</p> **also text to change** <p>text that should not change</p> <p>text that should not change</p> **last text to change** </div> <button id="replaceFirst">Replace First</button> <button id="replaceAll">Replace All</button>


Update 2017 (adrach): 2017 年更新(adrach):

It looks like several things changed since this was posted.自发布以来,似乎有几件事发生了变化。 Here is an updated version这是一个更新的版本

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

Original answer (Not working for current versions)原始答案(不适用于当前版本)

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

Source: http://api.jquery.com/contents/来源: http : //api.jquery.com/contents/

See In action见行动

Markup :标记:

 $(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" />

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

This changes only the first textnode这仅更改第一个文本节点

Just wrap the text you want to change in a span with a class to select.只需将要更改的文本用一个类包裹起来即可选择。

Doesn't necessarily answer your question I know, but, probably a better coding practice.我知道不一定能回答你的问题,但是,可能是更好的编码实践。 Keep things clean and simple保持事物干净和简单

<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>

Voilà!瞧!

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

For the specific case you mentioned:对于您提到的具体情况:

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

... this is very easy: ...这很容易:

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

You don't state how you want to generalize this.你没有说明你想如何概括这一点。 If, say, you want to change the text of the first text node within the <div> , you could do something like this:例如,如果您想更改<div>第一个文本节点的文本,您可以执行以下操作:

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

 $.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>

Simple answer:简单回答:

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

Here is yet another method : http://jsfiddle.net/qYUBp/7/这是一种方法: http://jsfiddle.net/qYUBp/7/

HTML HTML

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

JQUERY查询

var tmp=$("#header>div").html();
$("#header").text("its thursday").append(tmp);

Lots of great answers here but they only handle one text node with children.这里有很多很棒的答案,但他们只处理一个带有孩子的文本节点。 In my case I needed to operate on all text nodes and ignore html children BUT PRESERVE THE ORDERING.在我的情况下,我需要对所有文本节点进行操作并忽略 html 子节点,但保留顺序。

So if we have a case like this:所以如果我们有这样的案例:

<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>

We can use the following code to modify the text only AND PRESERVE THE ORDERING我们可以使用以下代码仅修改文本并保留顺序

 $('#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>

Here is the jsfiddle of it working这是它工作的jsfiddle

Problem with Mark's answer is that you get empty textnodes aswell.马克的回答的问题是你也得到了空的文本节点。 Solution as jQuery plugin:作为 jQuery 插件的解决方案:

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

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

I think you're looking for .prependTo().我认为您正在寻找 .prependTo()。

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

We can also select an element on the page and insert it into another:我们还可以选择页面上的一个元素并将其插入到另一个元素中:

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

If an element selected this way is inserted elsewhere, it will be moved into the target (not cloned):如果以这种方式选择的元素插入到别处,它将被移动到目标中(未克隆):

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

If there is more than one target element, however, cloned copies of the inserted element will be created for each target after the first.但是,如果有多个目标元素,则会在第一个目标之后为每个目标创建插入元素的克隆副本。

This is an old question but you can make a simple function like this to make your life easier:这是一个老问题,但您可以创建一个像这样的简单函数来让您的生活更轻松:

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

Example:例子:

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

Usage:用法:

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

2019 vesrsion - Short & Simple 2019 版 - 简短而简单

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

Explanation解释

document.querySelector('#your-div-id') is used for selecting the parent (the element which text you are about to change) document.querySelector('#your-div-id')用于选择父元素(您将要更改的文本元素)

.childNodes[0] selects the text node .childNodes[0]选择文本节点

.nodeValue = 'new text' sets text node value to "new text" .nodeValue = 'new text'将文本节点值设置为“新文本”


This answer is possibly inspired by Dean Martin's comment.这个答案可能受到 Dean Martin 评论的启发。 Can't say for sure since I've been using this solution for years now.不能肯定,因为我多年来一直在使用这个解决方案。 Just thought I should post this probability here because some people care about it more than the fact that this is the best solution.只是想我应该在这里发布这个概率,因为有些人更关心它而不是这是最好的解决方案。

Javascript approach. Javascript 方法。 select the parent div and we can use the firstChild.textContent选择父 div,我们可以使用 firstChild.textContent

let myDiv = document.getElementById("parentDiv");
myDiv.firstChild.textContent = "** New Text **"

Here's a recursive way:这是一种递归方式:

function changeInnerText(elm,text,newText) {
    if (elm == null) {
        return;
    }
    changeInnerTextHelper(elm.firstChild, text, newText);
}
function changeInnerTextHelper(elm, text, newText) {
    if (elm == null) {
        return;
    }
    if (elm.nodeType == 3 && elm.data == text) {
        elm.data = newText;
        return;
    }
    changeInnerTextHelper(elm.firstChild, text, newText);
    changeInnerTextHelper(elm.nextSibling, text, newText);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM