请教一下,如何用 js 合并连续的相同的 span

2021-11-02 09:44:05 +08:00
 shubei

=>

情已 逐晓云空

2413 次点击
所在节点    程序员
29 条回复
cyrbuzz
2021-11-02 11:24:00 +08:00
@shubei

2s 是可接受范围吧,正常浏览网站,像是 bilibili, DOMContentLoad 也要 1s 左右。
siweipancc
2021-11-02 11:41:35 +08:00
两个栈与一个计数器。源数据全部入栈 1 ; 1 出栈做中间计数然后入 2 栈; 1 出栈与计数匹配则 2 出栈合并后入 2 栈不匹配则跳过,同时清空计数。
while 打上去。
结尾 2 栈整个导出来渲染。
效率不会很高。
iPhone12
2021-11-02 14:29:13 +08:00
可以只创建 dom ,不渲染。
再通过 dom 的 api 进行 siblings 、text 操作拿到 text 。
iPhone12
2021-11-02 14:32:40 +08:00
let temp = document.createElement('div')
temp.innerHTML = '题上 html 内容'

// example

let text = temp.getElementsByClassName('match')[0].innerText
aguesuka
2021-11-02 14:58:46 +08:00
首先使用 DOMParser 解析成 dom 树, 先序遍历元素, 如果前一个元素和后一个元素的 tag 和 attr 相同, 则将后一个元素的子元素都 append 到前一个元素中, 并删除后一个元素.
2i2Re2PLMaDnghL
2021-11-02 15:51:39 +08:00
同上,new DOMParser().parseFromString(str, 'text/html') ,用 DOM 操作改完之后再转回 html 插入
然后从根节点开始对 children 作两次循环,第一遍吸收 nextSibling ,第二遍递归下降调用自身
autoxbc
2021-11-02 16:42:59 +08:00
强行在 String 阶段处理,本质就是写了一个简陋的 DOM 解析器
aguesuka
2021-11-02 16:43:05 +08:00
简单地写了一下, 还可以继续优化, 不过这样应该够用了.

function isText(target, node) {
return target !== null && target.nodeType === Node.TEXT_NODE
&& node.nodeType === Node.TEXT_NODE
}

function shouldMerge(target, node) {
if (target === null) {
return false
}

return target.nodeType === Node.ELEMENT_NODE
&& node.nodeType === Node.ELEMENT_NODE
&& node.getAttribute('class') === target.getAttribute('class')
}

/**
* @param rootNode {Node}
*/
function mergeChildrenNodes(rootNode) {
if (!rootNode.hasChildNodes()) {
return;
}
let preChild = rootNode.firstChild;
const markToRemove = []
for (let i = 1; i < rootNode.childNodes.length; i++) {
const child = rootNode.childNodes[i];
if (isText(preChild, child)) {
preChild.textContent += child.textContent;
markToRemove.push(child);
} else if (shouldMerge(preChild, child)) {
child.childNodes.forEach(node => preChild.appendChild(node));
markToRemove.push(child);
} else {
preChild = child;
}
}
markToRemove.forEach(node => node.parentNode.removeChild(node));
for (const node of rootNode.childNodes) {
mergeChildrenNodes(node);
}
}

function test() {
const dom = new DOMParser().parseFromString(`<\span>高<\/span>
<\span class="del">情<\/span>
<\span class="del">已<\/span>
<\span class="match"><\span class="add">逐<\/span><\span class="add">晓<\/span><\/span>
<\span class="match"><\span>云</span><\span>空</span><\/span>`, 'text/html')
mergeChildrenNodes(dom)
const theSpanWitchClassIsDel = dom.lastChild.lastChild.childNodes[1];
console.info(theSpanWitchClassIsDel)
console.assert(theSpanWitchClassIsDel.getAttribute)
console.assert(theSpanWitchClassIsDel.textContent === '情已')
}
shubei
2021-11-02 19:11:07 +08:00
@aguesuka 学习了

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/812340

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX