Range对象介绍

在web中有个不常用,但挺强大的一个对象Range。他表示一个包含节点与文本节点的一部分的文档片段。

1、创建Range实例

有三种办法可以得到一个Range, 一旦一个 Range 对象被建立,在使用他的大多数方法之前需要去设置他的临界点

  1. 通过 Range() 构造函数来得到Range, 新创建的对象属于全局 Document 对象
  2. 通过 Document.createRange 方法创建 Range
  3. 通过 Selection 对象来获取range

下面我们来一一介绍,介绍例子时候,使用一份html文档

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <div>
    <p>第一段文本</p>
    <p>第二段文本</p>
    <p>第三段文本</p>
    <p>第四段文本</p>
    <p>第五段文本在firefox中可以按住 ctr/command (windows/mac)键批量选中</p>
  </div>

 <div class="container">
  <input type="button" value="click me" onclick="showSelection()"/>
  <p>下面区域显示用鼠标选择的内容</p>
  <div id="show-selection">
  </div>
 </div>
</body>
<script>
const eleList = document.querySelectorAll('p');
</script>
</html>

1.1、Range() 构造函数

 // 使用Range构造函数新建Range实例range
 const range = new Range();
 // Range 起始位置在段落2之前
 range.setStartBefore(eleList[1]);
 // Range 起始位置在段落2之后,在这里相当于第三段之前
 // range.setStartAfter(eleList[1]);

 // Range 结束位置在段落3之后
 // range.setEndAfter(eleList[2]); 

 // Range 结束位置在段落3之前,在这里相当于第二段之后
 range.setEndBefore(eleList[2]); 
 // 以上本质上都是为了设置range的起点/终点.
 
 // 获取 selection 对象
 const selection = window.getSelection();

 // 添加光标选择的范围
 selection.addRange(range);

我们可以看到效果如下:
在这里插入图片描述
上述的第二段文本会被选中

1.2、Document.createRange

 const range2 = document.createRange();
 // range.setStart(startNode, startOffset);
 // startNode 用于设定 Range的起始位置, startOffset  必须为不小于0的整数。表示从startNode的开始位置算起的偏移量。
 // 设置range的起点
 range2.setStart(eleList[1], 0);
 // 设置range的终点,在这里是第三段话的第三个汉子
 range2.setEnd(eleList[2].firstChild, 3)
 selection.addRange(range2);
 // 获取 selection 对象
 const selection = window.getSelection();

效果如下图所示:
在这里插入图片描述

1.3、通过 Selection 对象来获取range

const showSelection = ()=>{
    const ele = document.getElementById('show-selection');
    const selection = document.getSelection();
    const selectLen = selection.rangeCount;
    if(selectLen > 0){ 
      let html = `你选取了${selectLen}段内容:<br />`;
      for(let i=0; i< selectLen; i++){
        const range = selection.getRangeAt(i);
        console.log(range);
        html += `${i+1}内容: ${range} <br />`;
      }
      ele.innerHTML = html;
    }
  }

点击上述按钮,效果如下所示:
在这里插入图片描述
在firefox浏览器中还可以按住command键选中多个文本区域
在这里插入图片描述

2、常用的range方法

2.1 设置range的起点和终点

如上所述,一旦一个 Range 对象被建立,在使用他的大多数方法之前需要去设置他的临界点。主要有如下的方法

  • range.setStart(startNode, startOffset); startNode 用于设定 Range的起始位置。startOffset 必须为不小于0的整数。表示从startNode的开始位置算起的偏移量。
  • range.setStartBefore 以其它节点为基准,设置 Range 的起点,range的开始点在该节点之前
  • range.setStartAfter 以其它节点为基准,设置 Range 的起点,range的开始点在该节点之后
  • range.setEndBefore 以其它节点为基准,设置 Range 的终点,range的开始点在该节点之前
  • range.setEndAfter 以其它节点为基准,设置 Range 的终点,range的开始点在该节点之后
    注意:使用后面四个方法设置的“起点”或“结束点”的父节点与referenceNode的父节点是同一个元素。

2.2 设置Range为Node节点及其内容

Range.selectNode() 方法将 Range 设置为包含整个 Node 节点及其内容。Range 的起始和结束节点的父节点与 referenceNode 的父节点相同

// selectNode
  var selectRange = document.createRange();
  var referenceNode = document.getElementsByTagName("div").item(0);
  selectRange.selectNode(referenceNode);
  console.log('设置Range的范围为选中的节点及其内容:', selectRange);

在这里插入图片描述

2.3 设置Range范围包含节点内容

Range.selectNodeContents() 方法用于设置 Range,使其包含一个 Node 的内容。

Range 的起始和结束节点的父节点即为引用节点。 startOffset 为 0, endOffset 则是引用节点包含的字符数或子节点个数。

// selectNodeContents
  var selectContentRange = document.createRange();
  referenceNode = document.getElementsByTagName("div")[0];
  selectContentRange.selectNodeContents(referenceNode);
  console.log('设置Range的范围为选中的节点:', selectRange);

在这里插入图片描述

2.4 克隆Range对象

Range.cloneRange()方法返回一个range对象,并且该对象的范围边界点与被克隆的range对象相同。

克隆的对象是复制过来的,而非引用,所以这两个对象双方各自做出的改变,都不会影响另一方。

const sourceRange = range.cloneRange();
sourceRange.selectNode(document.getElementsByTagName("div").item(0));
const cloneRange = sourceRange.cloneRange();
console.log('clone的range: ', cloneRange);

在这里插入图片描述

2.5 clone节点中的文档片段

Range.cloneContents() 返回一个 DocumentFragment,它是 Range 中所有的 Node 对象的副本。

使用" DOM 事件"添加的“事件侦听器”在克隆过程中不会被复制。 HTML属性事件与“DOM Core cloneNode”方法一样被复制。“HTML id属性”也将被克隆,这可能导致通过克隆导致无效的文档。

 // cloneContents
 const cloneContentsRange = range.cloneRange();
 cloneContentsRange.selectNode(document.getElementsByTagName("div").item(0));
 const documentFragment = cloneContentsRange.cloneContents();
 console.log('cloneContents: ', documentFragment);

在这里插入图片描述
这里需要注意:cloneRange返回的是一个Range对象,cloneContent返回的是一个HTML片段。

2.6 插入节点

Range.insertNode() 是在Range的起始位置插入节点的方法。

新节点是插入在 the Range起始位置。如果将新节点添加到一个文本 节点, 则该节点在插入点处被拆分,插入发生在两个文本节点之间

// insertNode
  const insertRange = document.createRange();
  const newNode = document.createElement("p");
  newNode.appendChild(document.createTextNode("在这里插入一个新的文本节点..."));
  insertRange.selectNode(document.getElementsByTagName("div").item(0));
  insertRange.insertNode(newNode);

在这里插入图片描述

2.7 移除Range至DocumentFragment中

Range.extractContents() 方法移动了Range 中的内容从文档树到DocumentFragment(文档片段对象)。

使用DOM事件添加的事件侦听器在提取期间不会保留。 HTML属性事件将按Node.cloneNode()方法的原样保留或复制。 HTML id属性也会被克隆,如果提取了部分选定的节点并将其附加到文档中,则可能导致无效的文档。

克隆了部分选定的节点,以包括使文档片段有效所需的父标记。

// extractContents
  var extractRange = document.createRange();
  extractRange.selectNode(document.getElementsByTagName("div").item(0));
  var extractDocumentFragment = extractRange.extractContents();
  console.log(extractDocumentFragment);

在这里插入图片描述

2.8 删除Range

Range.deleteContents() 移除来自 Document的Range 内容。
不像Range.extractContents一样,本方法不会返回一个包含删除内容的文本片段

// deleteContents
const delRange = document.createRange();
delRange.selectNode(document.getElementsByTagName("div").item(0));
delRange.deleteContents();

这样就会吧所选Range的div区域给删除了
在这里插入图片描述

3、总结

一个虽不常用,但很强大的API,在某些场景,比如只需要在局部渲染的时候就可以使用Range来实现。
贴一下所用到的测试代码

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <div>
    <p>第一段文本</p>
    <p>第二段文本</p>
    <p>第三段文本</p>
    <p>第四段文本</p>
    <p>第五段文本在firefox中可以按住 ctr/command (windows/mac)键批量选中</p>
  </div>

 <div class="container">
  <input type="button" value="click me" onclick="showSelection()"/>
  <p>下面区域显示用鼠标选择的内容</p>
  <div id="show-selection">
    
  </div>
 </div>

</body>

<script>

// 一旦一个 Range 对象被建立,在使用他的大多数方法之前需要去设置他的临界点。

    const eleList = document.querySelectorAll('p');
  // 1、通过 Range() 构造函数来得到Range, 新创建的对象属于全局 Document 对象
    const range = new Range();
    // Range 起始位置在段落2之前
    range.setStartBefore(eleList[1]);

    // // Range 起始位置在段落2之后,在这里相当于第三段之前
    // range.setStartAfter(eleList[1]);

    // Range 结束位置在段落3之后
    // range.setEndAfter(eleList[2]); 

    // Range 结束位置在段落3之前,在这里相当于第二段之后
    range.setEndBefore(eleList[2]); 

    // 获取 selection 对象
    const selection = window.getSelection();

    // 添加光标选择的范围
    // selection.addRange(range);

  // 2、通过 Document.createRange 方法创建 Range
    const range2 = document.createRange();
    // range.setStart(startNode, startOffset);
    // startNode 用于设定 Range的起始位置, startOffset  必须为不小于0的整数。表示从startNode的开始位置算起的偏移量。
    // 设置range的起点
    range2.setStart(eleList[1], 0);
    // 设置range的终点,在这里是第三段话的第三个汉子
    range2.setEnd(eleList[2].firstChild, 3)
    selection.addRange(range2);

  // 3、通过 Selection 对象来获取range

  const showSelection = ()=>{
    const ele = document.getElementById('show-selection');
    const selection = document.getSelection();
    const selectLen = selection.rangeCount;
    if(selectLen > 0){ 
      let html = `你选取了${selectLen}段内容:<br />`;
      for(let i=0; i< selectLen; i++){
        const range = selection.getRangeAt(i);
        console.log(range);
        html += `${i+1}内容: ${range} <br />`;
      }
      ele.innerHTML = html;
    }
  }

  // selectNode
  var selectRange = document.createRange();
  var referenceNode = document.getElementsByTagName("div").item(0);
  selectRange.selectNode(referenceNode);
  console.log('设置Range的范围为选中的节点及其内容:', selectRange);

  // selectNodeContents
  var selectContentRange = document.createRange();
  referenceNode = document.getElementsByTagName("div")[0];
  selectContentRange.selectNodeContents(referenceNode);
  console.log('设置Range的范围为选中的节点:', selectRange);

  // clone
  const sourceRange = range.cloneRange();
  sourceRange.selectNode(document.getElementsByTagName("div").item(0));
  const cloneRange = sourceRange.cloneRange();
  console.log('clone的range: ', cloneRange);

  // cloneContents
  const cloneContentsRange = range.cloneRange();
  cloneContentsRange.selectNode(document.getElementsByTagName("div").item(0));
  const documentFragment = cloneContentsRange.cloneContents();
  console.log('cloneContents: ', documentFragment);


  // insertNode
  const insertRange = document.createRange();
  const newNode = document.createElement("p");
  newNode.appendChild(document.createTextNode("在这里插入一个新的文本节点..."));
  insertRange.selectNode(document.getElementsByTagName("div").item(0));
  insertRange.insertNode(newNode);

  // extractContents
  var extractRange = document.createRange();
  extractRange.selectNode(document.getElementsByTagName("div").item(0));
  var extractDocumentFragment = extractRange.extractContents();
  console.log(extractDocumentFragment);

  // deleteContents
  const delRange = document.createRange();
  delRange.selectNode(document.getElementsByTagName("div").item(0));
  delRange.deleteContents();
</script>
</html>```

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

问白

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值