美文网首页js css html
如何用 js 选中一段文本

如何用 js 选中一段文本

作者: 涅槃快乐是金 | 来源:发表于2022-01-11 23:05 被阅读0次

    文本选择,在我们日常前端开发中并不常见,通常我们只有在富文本编辑器、段落文本复制等场景才会使用到。 功能实现很简单,只需要了解了 Range 对象的基本用法即可,今天就让我们一起来了解一下 Range 对象。

    首先,我们做一点点准备

    新建一个 html 文件,写一点简单的 html 片段。我们故意加入一些 span 来让 dom 结构变得复杂一些。 在浏览器打开这个网页,打开开发者工具,切换到 console,然后选择“上班”两个字。 到此,我们的所有准备完毕。

    现在,我们在 console 直接输入 js 代码,边调试边看效果。

    第一步,如何拿到选中区域

    window.getSelection()
    
    

    我们得到了一个 Selection 对象。

    让我们忽略掉那些很重要的细节,只看我们用得到的细节。 Selection 有一个原型方法 getRangeAt,它接受一个参数 index,表示选择第一个选区。 有小伙伴就要问了:难倒会有多个选区吗? 还真有。在 Firefox 上,按住 ctrl 按键,是可以多选的。

    image.png

    但是 Chrome 是不允许多选区的。 我们在 Selection 对象上继续调用 getRangeAt,得到第一个选区对象。

    window.getSelection().getRangeAt(0)
    
    

    在上图的 Range 对象中,我们主要关注两对属性 startContainerstartOffsetendContainerendOffset

    上图为我们的 DOM 结构,将其转化成框线图,方便分析。


    当我们选中“上班”两个字的时候,我们的 startend 在上图中两条黑线所在位置。 此时,startContanerendContainer 指的是 span_1 内的 #text(上班) 文本节点,文字“上”的左侧位置,在 #text(上班) 文本节点内 index = 0 的位置,所以 startOffset = 0,同理,endOffset = 2

    是不是有点蒙?我们换一个场景重新分析一下。我们选中“天不上”这三个字,再次获取一次 Range 对象。

    可以看到,此时的 startOffsetendOffset 都是 1,然后此时起止光标并不在同一个位置。

    从框线图我们看出,start 位置在 h1 内第一个的文本节点“明天”两个字中间,end 位置在 span_1 内“上班”两个字的中间。 所以此时的 startContainer = #text(明天)endContainer = #text(上班)。 start 这条线相对于 #text(明天) 的索引位置是 1,因此 startOffset = 1,同理 endOffset = 1

    至此,我们从获取选区信息基本已经了解了

    下一步,我们尝试通过 js 来更新选区

    从 console 可以看出,Range 对象有 setEnd 方法,它接收 node 和 offset 两个参数,也就是设置框线图内 end 所在位置。同理,也有类似的 setStart 方法来设置选区的 start 位置。 我们如果想要选中“不上班”三个字,我们可将 start 和 end 的节点都设置为最外层包裹元素 h1,如下图所示。

    那么此时 startOffsetendOffset 应该是多少呢? h1 元素,准确地说它包含了 5 个子节点,分别是:#text(明天)、span_0(不)、span_1(上班)、#text(,)、span_2(放假)。 我们可以直接把 start 放置到 #text(明天)span_0(不) 中间,span_0 是 h1 第 2 个子元素,那么它前面的空位 index = 1,因此 startOffset = 1。 同样,end 放置到 span_1(上班)#text(,) 中间,endOffset = 3

    const range = window.getSelection().getRangeAt(0)
    const h1 = document.getElementsByTagName('h1')[0]
    range.setStart(h1, 1)
    range.setEnd(h1, 3)
    

    我们可以看到,“不上班” 3 个字被顺利选中了。

    如何凭空选中

    上面所有操作的前提是我们已经选中了一段文本区域,如果我们没有进行任何选中操作,执行 getRangeAt(0) 会报错。

    此时,我们应该先通过 Selection 对象的 rangeCount 判断是否有选取,如果没有,可以调用 Selection.addRange 方法,新建一个选区。addRange 方法接收一个 Range 对象作为参数,我们可以通过 document.createRange 方法创建空选区,再把返回的 newRange 传给 addRange 方法即可。

    const newRange = document.createRange()
    newRange.setStart(window.span_1.childNodes[0], 1)
    newRange.setEnd(window.span_2.childNodes[0], 1)
    window.getSelection().addRange(newRange)
    

    这样就选中了“班,放”三个字,示意图如下。


    其他应用

    Range 对象的能力不仅如此,如果我们设置 start 和 end 为同一位置,那其实就等同于将光标移动到某个位置。 除此之外,还能进行节点的添加 insertNode 和删除 deleteContents,因此 Range 在富文本编辑器的开发中举足轻重。

    富文本编辑器的实现,今后有机会再和大家详细介绍,祝大家元旦节快乐。

    参考

    developer.mozilla.org/zh-CN/docs/… developer.mozilla.org/zh-CN/docs/…

    作者:CreditFE信用前端
    链接:https://juejin.cn/post/7047022519294885924

    相关文章

      网友评论

        本文标题:如何用 js 选中一段文本

        本文链接:https://www.haomeiwen.com/subject/pngicrtx.html