【问题标题】:How can I split a text node into spans of 3 words each?如何将文本节点拆分为每个 3 个单词的跨度?
【发布时间】:2012-11-25 07:16:56
【问题描述】:

假设我有这个 div:

<div> Let's say these are the words in my div </div>

我知道我可以通过这种方式将 div 中的每个单词包装成一个 span

$("div").contents().wrap('<span class="wrapper"/>');
//output:  <div><span class="wrapper"> Let's say these are the words in my div</span> </div>

但是,我想实现这一目标:

<div>
    <span class="wrapper">Let's say these</span>
    <span class="wrapper">are the words</span>
    <span class="wrapper">in my div</span>
</div>

每个特定数量的单词(本例:每3个单词)分成一组,每组单词单独包装。 p>


这些是我首先想到的:

1)我认为可以通过text()获取字符串和split(' ')组成一个数组,每个元素包含一个单词,写一个while循环来操作数组:

var a = 0;
var b = array.length;
while (a<b) {
    array[a] = "<span class="wrapper>" +  array[a]";
    a +=2;
    if (a>b) {
        a = b-1;
    }
    array[a] = array[a] + "</span>";
    a++;
}

那么只需简单地将.join('')数组和$("div").html(string)组成一个字符串;


2) 或者我可以在用text()获取后简单地使用正则表达式:

全局搜索包含a word + a space + a word + a space + another word的表达式

/(\w+\s+\w+\s+\w+)/g

将其替换为包裹在跨度中的内容

&lt;span&gt;$1&lt;/span&gt;

html() 在执行$("div").contents().eq(2).wrap('&lt;span class="wrapper"/&gt;') 之前的输出,如果有奇数输出。


这些是我想出的,我想知道,除了这些还有更好的方法吗?

实现它的最佳方法是什么(最快且需要最少的内存)?

【问题讨论】:

  • 我认为连接版本会更快,因为它没有运行“复杂”的正则表达式计算,但是,据我了解(并像我一样用一粒盐) t 自己运行测试),在 JS 中运行多个连接是一个非常昂贵的过程(我相信我在eloquentjavascript.net 中读到了这个)。所以是的,我没有答案。 :)
  • 如果你写的东西成功了,它可能会比 jQuery 版本更快,但你也需要考虑在开发人员大脑中“执行”什么。跨度>
  • @greg5green 是的,当然:)
  • Arch,最好使用 jQuery 之类的框架来处理 DOM 内容,因为它可以处理较旧的 document.layers (NS4) 和 document.all (IE4) 实现。我知道它会影响 1/1,000,000 的用户,但实际上并没有增加多少开销,并确保了可靠性。
  • Arch:还是用直接的 DOM 版本更新了我的答案,供您参考:)

标签: javascript jquery string performance


【解决方案1】:

这应该做你想做的:

在这里演示:http://jsfiddle.net/UQk7r/

$("div").each(function() {
    var out = [];
    var words = $(this).text()..trim().split(' ');
    for (var i = 0; i < words.length; i += 3) {
        out.push('<span class="wrapper">' + words.slice(i, i+3).join(' ') + '</span>');
    }
    $(this).html(out.join(' '));
});

这是 DOM 版本(没有 jQuery):

在这里演示:http://jsfiddle.net/cCege/2/

var divs = document.getElementsByTagName('div');
for (var i = 0; i < divs.length; i++) {
    var out = [];
    var words = divs[i].innerText.trim().split(' ');
    for (var j = 0; j < words.length; j += 3) {
        out.push('<span class="wrapper">' + words.slice(j, j+3).join(' ') + '</span>');
    }
    divs[i].innerHTML = out.join(' ');
}

最后,这是一个 DOM + RegEx 版本......这应该是你的最佳表现:

演示:http://jsfiddle.net/Xgm5q/1/

var divs = document.getElementsByTagName('div');
for (var i = 0; i < divs.length; i++) {
    divs[i].innerHTML = '<span class="wrapper">' 
            + divs[i].innerText.trim().replace(/(([^\s]+\s+){2}[^\s]+)\s+/g, '$1</span> <span class="wrapper">')
            + '</span>';
}​

【讨论】:

    【解决方案2】:

    为了表现:

    var elems = document.getElementsByTagName('div');
    
    for (var j=elems.length; j--;) {
        var txtArr = elems[j].textContent.replace(/([a-zA-Z]+)\s([a-zA-Z]+)\s([a-zA-Z]+)/g, '$1 $2 $3* ').split('*'),
            txtElm = document.createDocumentFragment(),
            span   = document.createElement('span');
    
        for (i=0; i<txtArr.length; i++) {
            if (/\S/.test(txtArr[i])) {
                var sp   = span.cloneNode(true),
                    text = document.createTextNode(txtArr[i]);
    
                sp.appendChild(text);
                txtElm.appendChild(sp);
            }
        }
    
        elems[j].innerHTML = '';
        elems[j].appendChild(txtElm)
    }
    ​
    

    FIDDLE

    【讨论】:

    • DOM 操作会比字符串/数组操作更快吗?我敢打赌没有。 ;)
    • @TheSmose - 让我们试试看 -> JSPERF
    • 不错。为你+1。 FTI,这是我的正则表达式之一:jsperf.com/funny-stuff/2
    • @TheSmose - 不能让最后一个工作,也没有花时间修复它,但我的浏览器仍然是最快的,但这真的是因为使用了片段并且只改变 DOM 一次(技术上两次),这就是像这样的函数的滞后。
    猜你喜欢
    • 2010-10-21
    • 1970-01-01
    • 2014-05-23
    • 2020-07-24
    • 1970-01-01
    • 1970-01-01
    • 2010-10-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多