【问题标题】:How to wrap each word of an element in a span tag?如何将元素的每个单词包装在 span 标签中?
【发布时间】:2023-03-29 23:43:02
【问题描述】:
$("div.date")
    .contents()
    .filter(
        function(){
            return this.nodeType != 1; 
        })
    .wrap("<span/>");

我是新手,我认为代码可以解决问题,但它将所有内容都包装在 &lt;span&gt; 中,如下所示:

&lt;div class='date'&gt;&lt;span&gt;2011 年 12 月 22 日&lt;/span&gt;&lt;/div&gt;

它应该是这样的:

<div class='date'>
  <span>Dec</span>
  <span>22,</span>
  <span>2011</span>
</div>

【问题讨论】:

  • 您可能想查看Lettering 插件。
  • 尝试通过举例说明您想要的内容来改进您的问题。一个更好的问题名称似乎是“如何将元素的 每个单词 包装在 span 标签中?”

标签: javascript jquery


【解决方案1】:

对于这个简单的任务,您不需要 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>");
}

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

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

【讨论】:

  • 虽然这是一个很好的答案,但为什么将 isn't 包装为 2 个不同的词?
  • @HenrikPetterson 那是因为\w 匹配任何单词 字符(字母数字和下划线),而' 实际上不是单词;)你可以使用\S相反,它匹配任何非空格字符(空格、制表符、换行符等)的字符regexr.com/3d9p5
  • '&lt;span class="name"&gt;hello world &lt;/span&gt;' 不起作用,它不能很好地处理 html 属性。
【解决方案2】:

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

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

Live example

【讨论】:

    【解决方案3】:

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

    这是我想出的一个 jsfiddle,它保留了 HTML(元素及其属性)。这个小 sn-p 的缺点是,如果您将事件绑定到元素的内容,那么它们将丢失,因为 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 之类的属性时会遇到问题。你知道怎么解决吗?
    • @ClickerMonkey 感谢您的解决方案,为了获得更好、更安全的正则表达式,请在此处查看我的答案stackoverflow.com/a/66380709/1966247
    • @user500665 你修好了吗?
    【解决方案4】:

    我需要给每个单词一个特定的 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>
    

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

    【讨论】:

      【解决方案5】:

      经过大量研究,我能够通过使用 Regex 的 Negative lookbehind 功能安全地做到这一点。

      htmlStr.replace(/(?<!(<\/?[^>]*|&[^;]*))([^\s<]+)/g, '$1<span class="word">$2</span>')
      

      【讨论】:

      • ^ 适用于所有不同情况的唯一答案 ^
      • 并非所有浏览器都支持向后看
      • react native 不支持向后看
      【解决方案6】:
      var $div = $('.words');
      var divWords = $div.text().split(/\s+/);
      $div.empty();
      $.each(divWords, function(i,w){
        $('<span/>').text(w).appendTo($div);
      });
      

      然后

      <div class="words">Why hello there, world!</div>
      

      变成

      <div class="words">
        <span>Why</span>
        <span>hello</span>
        <span>there,</span>
        <span>World!</span>
      </div>
      

      【讨论】:

        【解决方案7】:

        这是你想要达到的目标吗?

        <span><div class="date">Dec 22, 2011</div></span>
        

        如果是这样:

        $('div.date').wrap('<span/>');
        

        或者你想得到这个:

        <span>Dec</span> <span>22,</span> <span>2011</span>
        

        这样的事情应该可以解决问题:

        var dateInner = $('div.date');
        var wraps = [];
        $.each(dateInner.text().split(' '), function (key, value) {
          wraps.push = '<span>' + value + '</span>';
        });
        
        dateInner.html(wraps.join(''));
        

        【讨论】:

          【解决方案8】:

          如果你使用 jQuery,试试this

          具体可以找个例子说明如何拆分成单词here

          引用:

          下面是 .lettering('words') 方法的示例:

          <p class="word_split">Don't break my heart.</p>
          
          <script>
          $(document).ready(function() {
            $(".word_split").lettering('words');
          });
          </script>
          

          会生成:

          <p class="word_split">
            <span class="word1">Don't</span>
            <span class="word2">break</span>
            <span class="word3">my</span>
            <span class="word4">heart.</span>
          </p>
          

          【讨论】:

            【解决方案9】:

            只是建立在 Xeon06 的优秀答案之上。

            我必须为同一页面上的多个相同元素执行此操作。

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

            【讨论】:

              猜你喜欢
              • 2016-08-28
              • 1970-01-01
              • 2016-11-11
              • 1970-01-01
              • 2014-09-07
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多