如何将元素的每个单词包装在 span 标签中?

IT技术 javascript jquery
2021-02-17 07:35:33
$("div.date")
    .contents()
    .filter(
        function(){
            return this.nodeType != 1; 
        })
    .wrap("<span/>");

我是新手,认为代码可以解决问题,但它包含了所有内容,如下<span>所示:

<div class='date'><span>2011 年 12 月 22 日</span></div>

它应该是这样的:

<div class='date'>
  <span>Dec</span>
  <span>22,</span>
  <span>2011</span>
</div>
6个回答

不需要jQuery 来完成这个简单的任务。String.prototype.replace正则表达式应该可以解决问题。

我刚刚制作了一些简单的实用函数,用于包装字母、单词和线条:

/**
 * Wraps a string around each character/letter
 *
 * @param {string} str The string to transform
 * @param {string} tmpl Template that gets interpolated
 * @returns {string} The given input as splitted by chars/letters
 */
function wrapChars(str, tmpl) {
  return str.replace(/\w/g, tmpl || "<span>$&</span>");
}

/**
 * Wraps a string around each word
 *
 * @param {string} str The string to transform
 * @param {string} tmpl Template that gets interpolated
 * @returns {string} The given input splitted by words
 */
function wrapWords(str, tmpl) {
  return str.replace(/\w+/g, tmpl || "<span>$&</span>");
}

/**
 * Wraps a string around each line
 *
 * @param {string} str The string to transform
 * @param {string} tmpl Template that gets interpolated
 * @returns {string} The given input splitted by lines
 */
function wrapLines(str, tmpl) {
  return str.replace(/.+$/gm, tmpl || "<span>$&</span>");
}

用法很简单。只需传入要包装的字符串作为第一个参数。如果您需要自定义标记,请将其作为第二个参数传入,而$&由每个字符/单词/行替换。

var str = "Foo isn't equal\nto bar.";
wrapChars(str); // => "<span>F</span><span>o</span><span>o</span> <span>i</span><span>s</span><span>n</span>'<span>t</span> <span>e</span><span>q</span><span>u</span><span>a</span><span>l</span> <span>t</span><span>o</span> <span>b</span><span>a</span><span>r</span>."
wrapWords(str); // => "<span>Foo</span> <span>isn</span>'<span>t</span> <span>equal</span> <span>to</span> <span>bar</span>."
wrapLines(str); // => "<span>Foo isn't equal</span> <span>to bar.</span>"
@HenrikPetterson这是因为\w 比赛的任何单词字符(字母数字和下划线),并且'其实不是一个字;)你可以使用\S来代替,该匹配任何字符不是一个空白字符(空格,制表符,换行符等)。regexr.com/3d9p5
2021-04-23 07:35:33
虽然这是一个很好的答案,但为什么它会包装isn't为 2 个不同的单词?
2021-04-25 07:35:33

它会比那更复杂一点。您将不得不找出所有单词并将它们重新附加到您的元素中,包裹在一个跨度中。

var words = $("p").text().split(" ");
$("p").empty();
$.each(words, function(i, v) {
    $("p").append($("<span>").text(v));
});

活生生的例子

如果您的元素内容包含子元素 (HTML),则上述解决方案没有用。

这是我提出的一个 jsfiddle,它保留了 HTML(元素及其属性)。这个小片段的缺点是,如果您将事件绑定到元素的内容,那么它们将丢失,因为 innerHTML 被重新分配给其他内容。

此代码不需要任何特殊库(如 jQuery)。

https://jsfiddle.net/4b5j0wjo/3/

var e = document.getElementById('words');
e.innerHTML = e.innerHTML.replace(/(^|<\/?[^>]+>|\s+)([^\s<]+)/g, '$1<span class="word">$2</span>');
这很好,但是当class子元素上有属性时会遇到问题你知道怎么修吗?
2021-04-19 07:35:33
@user500665 你修好了吗?
2021-05-05 07:35:33
@ClickerMonkey 感谢您的解决方案,为了更好和安全的正则表达式,请在此处查看我的答案stackoverflow.com/a/66380709/1966247
2021-05-06 07:35:33

我需要给每个单词一个特定的 id,所以,作为一个新手,我研究了以前发布的答案代码。从 Brad Christie 和 Daniel Tonon 的代码开始,我使用 .addClass 来实现这个结果:

    $('.mydiv').each(function(){ 
    var words = $(this).text().split(/\s+/);
    var total = words.length;
    $(this).empty();
    for (index = 0; index < total; index ++){
      $(this).append($("<span /> ").addClass("myclass_" + index).text(words[index]));
      }
    })

输出:

    <div class="mydiv">
       <span class="myclass_0">bla</span>
       <span class="myclass_1">bla</span>
       <span class="myclass_2">bla</span>
    </div>

从...开始:

    <div class="mydiv">bla bla bla</div>

它非常适合我的需求。也许一些专家程序员可以更好地调整它!

经过大量研究,我能够通过使用正则表达式的负后视功能安全地做到这一点。

htmlStr.replace(/(?<!(<\/?[^>]*|&[^;]*))([^\s<]+)/g, '$1<span class="word">$2</span>')
^ 唯一适用于所有不同情况的答案 ^
2021-04-30 07:35:33
并非所有浏览器都支持后视
2021-05-13 07:35:33