用typescript撸一个让元素高亮的库

916 阅读2分钟
原文链接: segmentfault.com

一直都想做一个js库,而且github上没有太多重复的轮子那种(轮子太多自己造就没必要了),最好是自己会用得上。思前想后,决定做一个高亮文字的js库。刚好最近接触一段时间typescript,可以拿来练练手,毕竟自己的东西怎么折腾都可以。


如何让一个元素的文字高亮,或者鼠标选中的文字高亮?

  • 让一个元素的文字高亮很简单,直接
<p>这是一段文字</p>    ==>    <p><mark>这是一段文字</mark></p>

可以为元素内的文字加上一个容器,并且不能够影响到文字的换行。之后为mark元素加上样式就可以了

  • 让鼠标选中的文字高亮

高亮鼠标选中的文字需要处理的情况就复杂一点了
例如
jsfiddle例子

  1. 当鼠标选中一个元素中的部分文字
// 鼠标选中了在p元素中的一部分文字,假设是 “一段” 这两个字
// 那么则需要处理成以下模样
<p>这是一段文字</p>    ==>    <p>这是<mark>一段</mark>文字</p>
  1. 鼠标选中的文字跨越多个元素
<div>
  <p>1这是一段文字</p>
</div>
<div>
  <p>2这是一段文字</p>
</div>

处理以上的这些情况,则需要用到Range对象

document.addEventListener('click', (event) => {
 let selection = window.getSelection();
 console.log(selection)
 if (selection.rangeCount) {
   let range = selection.getRangeAt(0)
   console.log(range)
 }
})

我们可以通过Selection对象进而拿到Range.在chrome上我们用鼠标只能选中一个Range,firefox上按住ctrl则可以多选。

Range.extractContents()
把 Range 的内容从文档树移动到文档片段中。这会造成选区内的元素消失在dom树上
Range.insertNode()
在 Range 的起点处插入节点。

通过Range.extractContents()可以拿到documentFragment,之后对document Fragment进行相应的处理之后插入到Range中。
但是简单的进行insertNode会发生换行的效果。
具体原因看看代码就知道了。
例子中的p元素插入到Range时,包含了其父元素div,所以发生换行。

所以这里面还是有很多坑要踩,下次有空再写吧。
最后附上自己的写的js库,虽然还有很多待完善的地方。喜欢就给个start吧。