Range和Selection 您所在的位置:网站首页 rangecount Range和Selection

Range和Selection

2024-01-03 08:17| 来源: 网络整理| 查看: 265

前言 - 克服焦虑,前端未死

各位小伙伴们你们好呀!这里是梅利奥猪猪,一名持续进步的讲师。

相信最近的就业环境,让不少XDM特别焦虑,我个人的看法,就只能尽可能提高自己的竞争力,只有自己足够强大了,才能解决焦虑,我们要学会去适应环境。顺便找些大佬的文章以及大佬朋友圈发的,大家有兴趣可以看下

张鑫旭大佬前一阵子写的也谈“前端已死”

其中旭神此篇文章的部分截图

旭神建议一.jpg

旭神建议二.jpg

以下是mini-vue作者阿崔的观点

阿崔就业建议.jpg

上面阿崔说了有技术博客,参与过开源项目,哈哈老猪我好像都有=v=!秉着己所不欲勿施于人的态度,我会带头卷,所以XDM一起进步吧!

哈哈,不管咋样,前面分享的大佬们,他们意思都指向了同一个点,那就是为了自己而学习,我这边想和我带过的各位小伙伴说,也是我经常说的,学习是自己的,焦虑解决不了什么问题,为了自己努力变强吧,骚年

teacher.jpg

那扯回正题,上次富文本专栏更新了前端冷知识&富文本热知识之基础Selection和Range(建立兴趣篇),这次就稍微展开聊聊Range和Selection,当你看完这篇文章,会让你收获以下内容

如何获取用户选区 用户鼠标选中同一段文字,是从左边滑到右边选中的,还是从右边往左边选中的? 选择了一段文字,如果不选择,光点击个字符的前后(比如光标的位置)我们能知道具体位置在哪里吗 如何设置用户选区 js能生成个范围(range)吗?,然后让这段范围变成选中的范围吗? Range和Selection可以做什么

可以获取现有选中的内容,选择/取消全部 或 部分选中内容,从文档中删除所选部分,或将其包装到一个标签中等

以下为应用场景

富文本 划词翻译 网页批注 等等 学习Range Range是什么

本质上是一对边界点,范围起点和范围终点

先展示这么一段代码,然后用浏览器打开

Example:我是i标签里面的内容and我是b标签里面的东西

接着我们选中一些文字

如图,我们选中的内容,p标签里面的前2个子节点,一个是文本节点Example:,一个是i标签的内容我是i标签里面的内容,此时其实就有了Range对象

初识range选中文字.jpg

js创建Range对象

接下来我们来聊下创建range对象以及对应实例上的一些api

// 实例化对象 const range = new Range()

设置起点和终点的api - 设置边界(前闭后开)

range.setStart(node, offset) // 包含 range.setEnd(node, offset) // 不包含

以我们前面的例子为例

Example:我是i标签里面的内容and我是b标签里面的东西 文本节点 - Example: - offset为0 dom节点 - 我是i标签里面的内容 - offset为1 文本节点 - and - offset为2 dom节点 - 我是b标签里面的东西 - offset为3

此时如果这样设置

range.setStart(p, 0) // 将起点设置为p的第0个子节点,即文本节点Example: range.setEnd(p, 2) // 将终点设置为p的第2个子节点(但不包含),即终点是and文本节点,不包含 alert(range)

此时完整代码如下,我们可以用alert(range)看下效果怎么样,根据前面的分析范围应该是到i标签结束

学习selection和range Example:我是i标签里面的内容and我是b标签里面的东西 { const p = document.querySelector('p') const range = new Range() range.setStart(p, 0) range.setEnd(p, 2) alert(range) }

alert内容看看.jpg

接着给兄弟姐妹们一个思考题,此时如果我把代码改成

range.setStart(p, 1) range.setEnd(p, 3)

大家猜alert后的答案是啥?哈哈是不是贼简单,答案就是

第一道思考题答案.jpg

那如果我们想选中节点里的部分文字,那该怎么设置起点和终点呢

选中部分文字.jpg

其实还是差不多的老套路,设置起点和终点

起点第一个文本节点,字母a是第三个字符,即索引是2 终点是dom节点,i标签的文字里前面,因为前闭后开,所以索引是5 { const p = document.querySelector('p') const i = document.querySelector('i') const b = document.querySelector('b') const range = new Range() // range.setStart(p, 1) // range.setEnd(p, 3) // 选中 -> ample:我是i标签 range.setStart(p.firstChild, 2) range.setEnd(i.firstChild, 5) alert(range) }

选择部分文字演示.jpg

还有些其他api设置起点终点,这里就不赘述了有兴趣的XDM可以去查下mdn的文档

setStartBefore(node) - 将起点设置在node前面 setStartAfter(node) - 将起点设置在node后面 setEndBefore(node) - 将终点设置在node前面 setEndAfter(node) - 将终点设置在node后面

注意了,node既可以是文本节点,也可以是元素节点,对于文本节点,offset偏移的是字符数,对于元素节点则是子节点数

range实例上的属性

前面我们已经学会了如何创建range对象,并且通过alert也看到了范围是否是我们预测的结果,接下去我们把alert换成console.log来看看range实例上的属性

打印range对象.jpg

我们来分析一波

startContainer和startOffset: 起始节点和偏移量 在前面的例子里,起点容器就是p的文本节点,offset就是2 endContainer和endOffset: 结束节点和偏移量 在前面的例子里,终点容器就是i的文本节点,offset就是5(前闭后开5这个取不到) collapsed: 布尔值,开始和结束的点在同一点上则为true 在前面的例子里,因为起点和终点是2个不同的点所以为false commonAncestorContainer: 在范围内所有节点中最近的共同祖先节点 在前面的例子里,那当然就是我们的p标签 range实例上的其他方法

Range-MDN文档

其中有一些添加,删除,提取方法还是挺有意思的,有兴趣的小伙伴可以自行尝试下

学习Selection 概念

Range是用于管理选择范围的对象,他们在视觉上不会选择任何内容,在视觉上选择文档需要用到Selection对象,通过window.getSelection()来获取,理论上一个选择可以包括0个或者多个范围,实际上,只有Firefox允许在文档中选择多个范围

Selection的起点称为anchor,终点称为focus,在文档中,终点可能在起点之前,比如选择同一段文字,用户可以从左往右选中(forward方向),也可以从右往左选中(backward方向)

比如举个例子,我们选中同一段文字Example,然后在控制台打印window.getSelection()

forward方向.jpg

backward方向.jpg

Selection主要属性 anchorNode: 选择的起始节点 anchorOffset: 选择开始的anchorNode的偏移量 focusNode: 选择的结束节点 focusOffset: 选择focusNode的偏移量 isCollapsed: 返回一个布尔值用于描述选区的起始点和终止点是否位于一个位置(即是否框选) rangeCount: 返回选区 (selection) 中 range 对象数量,除了火狐其他浏览器都是1 type: 只读属性,其返回的是当前选择的类型 None: 当前没有选择。 Caret: 选区已折叠(即 光标在字符之间,并未处于选中状态)。 Range: 选择的是一个范围。 Selection事件

有些事件可以跟踪选择

onselectstart() 当选择从element开始时(例如用户按下鼠标键开始移动鼠标) 阻止默认行为会使选择无法开始 onselectionchange 当选择变动时 此事件只能在document上监听

所以我们可以写个这样的综合案例

学习selection和range input { width: 400px; } Example:我是i标签里面的内容and我是b标签里面的东西 From To isCollapsed { document.addEventListener('selectionchange', () => { // 获取起始节点,起始节点偏移量,结束节点,结束节点的偏移量,起始点和终点是否在一个位置 const { anchorNode, anchorOffset, focusNode, focusOffset, isCollapsed } = document.getSelection() // 给from的input框赋值 from.value = `${anchorNode && anchorNode.data} : ${anchorOffset}` // 给to的input框赋值 to.value = `${focusNode && focusNode.data} : ${focusOffset}` // 选区是否存在 赋值给flag的表单框 flag.value = isCollapsed }) }

接着我们来选择几个区域来看下,很明显就能看到选区的开始和结束节点以及偏移量

选区节点偏移量展示.gif

有没有看到里面有个单词是and,接着我们来测试下点击这个单词几个字符的前后,看下能不能获取到用户详细点击的位置,以及isCollapsed是否会变成true(因为我们没有选中范围,只是点击,如果是个输入框,那就是相当于设置光标位置)

确定光标的位置.gif

嗯明显是能获取到用户点击的位置的,也能看到isCollapsed字段变成了true

获取选中的内容 作为文本只需要调用window.getSelection().toString() 作为dom节点 获取range实例并调用cloneContents()方法 window.getSelection().getRangeAt(index).cloneContents() 如果是火狐需要遍历,因为range可能是多个,一般浏览器取索引0就可以了 getRangeAt(index)方法可以类比字符串方法charAt(index),就是获取对应索引的项,charAt是获取字符串对应索引的那一项,getRangeAt就是获取所有范围里对应索引的那一项,因为一般浏览器就只能选一个range,所以一般传0

那接下来我们继续写个例子,看下获取选中内容

学习selection和range input { width: 400px; } Example:我是i标签里面的内容and我是b标签里面的东西 复制文本内容 复制选择内容包含标签 { document.addEventListener('selectionchange', () => { const selection = window.getSelection() const rangeCount = selection.rangeCount if (rangeCount > 0) { // 获取文本内容 const str = selection.toString() copyText.innerHTML = str copyTag.innerHTML = '' const range = selection.getRangeAt(0) // 获取带标签的内容 const contents = range.cloneContents() range && copyTag.appendChild(contents) } }) }

获取内容.gif

很明显,前者只能获取纯文本,后者可以获取标签内容

设置选区

之前在我们学习range的时候,细心的小伙伴应该发现,在我们创建range对象后,即使设置了起点终点,页面上也没有选中文本

const p = document.querySelector('p') const i = document.querySelector('i') const b = document.querySelector('b') const range = new Range() // range.setStart(p, 1) // range.setEnd(p, 3) // 选中 -> ample:我是i标签 range.setStart(p.firstChild, 2) range.setEnd(i.firstChild, 5)

那这里我们要学习如何设置选区,其实最简单的方法即使addRange,注意这个api使用的时候,最好先清除下所有的选区,具体api是removeAllRanges

看猪哥这样操作下(开个延时器)

const p = document.querySelector('p') const i = document.querySelector('i') const b = document.querySelector('b') const range = new Range() // range.setStart(p, 1) // range.setEnd(p, 3) // 选中 -> ample:我是i标签 range.setStart(p.firstChild, 2) range.setEnd(i.firstChild, 5) // 新增延时器 setTimeout(() => { window.getSelection().removeAllRanges() window.getSelection().addRange(range) }, 3000);

3s后选中范围.gif

3秒后,范围被选上了,XDM看到没!

Selection实例上的方法

Selection-MDN文档

同之前提供的Range的文档,有兴趣的小伙伴也可以自行尝试

总结

感谢各位看到现在的XDM,今天这篇水文也到此结束了,简单总结下,我们今天应该对富文本的range和selection又有了点认识,知道了如何设置选区及获取选区

获取选区 // 获取selection实例 const selection = document.getSelection() // 获取文本 selection.toString() // 获取带标签的内容 文档碎片 selection.getRangeAt(index).cloneContents() 设置选区 // 获取selection实例 const selection = document.getSelection() // 先移除所有的范围 selection.removeAllRanges() // 添加范围 selection.addRange(range) 彩蛋

听说现在gpt写技术博客很厉害,担心自己写的水过头,赶紧看下gpt写的会不会比我更详细,测试搞起!然后发现还是挺详细的,但他没有代码运行的效果,没有gif图,那就是我的优势了(狗头保命),希望XDM看完后能有所收获!那这次水文到此结束!



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有