高 情 已 逐晓 云空
=>
高 情已 逐晓云空
1
shubei OP <\span>高<\/span>
<\span class="del">情<\/span> <\span class="del">已<\/span> <\span class="match"><\span class="add">逐<\/span><\span class="add">晓<\/span><\/span> <\span>云</span> <\span>空</span> |
2
shubei OP .. 可以注入的竟然
|
3
shubei OP <\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> => <\span>高<\/span> <\span class="del">情已<\/span> <\span class="match"><\span class="add">逐晓<\/span><\span>云空</span><\/span> |
4
AoEiuV020 2021-11-02 09:52:21 +08:00
感觉只能普通的循环遍历然后一个一个判断构造新的,
|
6
zhea55 2021-11-02 10:01:09 +08:00
用 jquery 的话,非常简单。
找到这些所有 span 的父节点 $(parentNode).text() |
9
shubei OP 主要有 match 这种的嵌套,双指针好像不好使
|
10
zhea55 2021-11-02 10:20:17 +08:00
@shubei 迭代的时候,把当前循环元素的 classname 拿出来,
在当前循环元素的 siblings 里面查找这个选择器。就拿到了所有同类,然后.text(),然后去空格。 然后下一个的 classname 要是和上次循环的一样,continue 再说下去,代码都给你写好了。 |
11
rongchuan 2021-11-02 10:28:49 +08:00
最简单的方式,获取 dom 字符串,用正则匹配处理,想咋弄都行。弄完如果没有光标需求,直接 innerHTML 完事。要操作光标就用 appendChild
|
12
shubei OP @zhea55 额,首先我这个就是单纯的字符串,并没有渲染,所以 siblings 、text 这些都不能用(因为就是 dom 节点过多,所以在渲染前用 js 合并一下的),然后对于字串符而言,我遇到的第一个问题就是用什么 split ,我最早的版本是用</span>,加了 match 之后不好使了
|
13
zhea55 2021-11-02 10:33:34 +08:00
@shubei 你这些数据,应该是入库之前就应该把数据整理好。
入库前爬取程序,一定是有 dom 节点的。 你要处理字符串的话,即使你用正则表达式,还是容易出现很多异常情况。 远远没有处理 dom 节点的代码可靠。 |
14
zjsxwc 2021-11-02 10:34:19 +08:00
搞个 html parser https://github.com/andrejewski/himalaya
后当普通数据处理呗 |
16
cyrbuzz 2021-11-02 10:38:06 +08:00
这个用 CSS 选择器啦。
``` let plus = document.querySelectorAll("span + span") let temp1 = plus[0] temp1.previousSibling.innerText += temp1.innerText temp1.parentElement.removeChild(temp1) ``` 首先遍历一遍 span ,没有 class 的一律先加一个虚拟 class ,然后把所有 class 找出来,去重,所有 class 挨个跑上面的代码,最后把虚拟的 class 去掉就完事了。 |
18
cyrbuzz 2021-11-02 10:51:47 +08:00
|
19
shubei OP @cyrbuzz 也可能是我别的地方有问题?我是用的 v-html 。原文 span 比较多,接口 200ms ,js 循环一遍 140ms ,但是渲染出来就要 2s 左右了
|
20
ookkxw 2021-11-02 11:17:24 +08:00
感觉纯 string 处理难点在于切割同时还要区分有没有子节点,我写的话先全部<\/span>切割掉变成数组,然后循环变成 VDOM tree ,接下来就简单了
|
21
cyrbuzz 2021-11-02 11:24:00 +08:00
|
22
siweipancc 2021-11-02 11:41:35 +08:00 via iPhone
两个栈与一个计数器。源数据全部入栈 1 ; 1 出栈做中间计数然后入 2 栈; 1 出栈与计数匹配则 2 出栈合并后入 2 栈不匹配则跳过,同时清空计数。
while 打上去。 结尾 2 栈整个导出来渲染。 效率不会很高。 |
23
iPhone12 2021-11-02 14:29:13 +08:00
可以只创建 dom ,不渲染。
再通过 dom 的 api 进行 siblings 、text 操作拿到 text 。 |
24
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 |
25
aguesuka 2021-11-02 14:58:46 +08:00
首先使用 DOMParser 解析成 dom 树, 先序遍历元素, 如果前一个元素和后一个元素的 tag 和 attr 相同, 则将后一个元素的子元素都 append 到前一个元素中, 并删除后一个元素.
|
26
2i2Re2PLMaDnghL 2021-11-02 15:51:39 +08:00
同上,new DOMParser().parseFromString(str, 'text/html') ,用 DOM 操作改完之后再转回 html 插入
然后从根节点开始对 children 作两次循环,第一遍吸收 nextSibling ,第二遍递归下降调用自身 |
27
autoxbc 2021-11-02 16:42:59 +08:00
强行在 String 阶段处理,本质就是写了一个简陋的 DOM 解析器
|
28
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 === '情已') } |