素材牛VIP会员
一个大的DOM结构,里面的元素node是否有唯一且稳定的标示,可以在刷新后再选中它?
 超***媒  分类:JavaScript  人气:862  回帖:3  发布于6年前 收藏

如题,我们需要做一个针对网页的笔记系统。
用户划选时,我们可以获得起始点的node,直接操作显示高亮。

我们遇到的难题是:当用户离开后,再次打开这个页面时,我们如何定位回去这个节点node。(已知:网页的节点不会变化,因为我们缓存的)

PS:我们不能给网页上的节点添加id之类的东西

讨论这个帖子(3)垃圾回帖将一律封号处理……

Lv4 码徒
gu***un UI设计师 6年前#1

花了点时间实现了下,随便找了几个网页测试,暂时没发现问题。
首先打开网页A,执行下面的代码:

let sel = window.getSelection();
let range = sel.getRangeAt(0);
let startNode = range.startContainer;
let endNode = range.endContainer;

//startContainer是不是文本节点,是的话存储父节点的信息
if (startNode.nodeType == 3) {
  var startIsText = true;
  var startFlag = startNode.parentNode;
  startNode = startNode.nodeValue;
} else {
  var startIsText = false;
  var startFlag = startNode;
}
if (endNode.nodeType == 3) {
  var endIsText = true;
  var endFlag = endNode.parentNode;
  endNode = endNode.nodeValue;
} else {
  var endIsText = false;
  var endFlag = endNode;
}

let startOffset = range.startOffset; 
let endOffset = range.endOffset; 

let startTagName = startFlag.nodeName;
let startHTML = startFlag.innerHTML;

let endTagName = endFlag.nodeName;
let endHTML = endFlag.innerHTML;

//这个是要存储到数据库的信息
let rInfo = {
  startNode,
  startOffset,
  startIsText,
  startTagName,
  startHTML,

  endNode,
  endOffset,
  endIsText,
  endTagName,
  endHTML  
};
//存在localStorage里测试
window.localStorage.setItem("r", JSON.stringify(rInfo));

然后关闭网页A,再重新打开,执行下面的代码:

//根据tabName和innerHTML定位到相应节点
function findEle(tagName, innerHTML) {
  let list = document.getElementsByTagName(tagName);
  for (let i = 0; i < list.length; i++) {
    if (list[i].innerHTML == innerHTML) {
      return list[i];
    }
  }
}

//重新显示选中区域的函数
function show({startNode,startIsText,startOffset,endNode,endIsText,endOffset},sP,eP) {
  var s, e;
  //判断原来的选区是不是由文本节点开始,分开处理
  if (startIsText) {
    let childs = sP.childNodes;
    for (let i = 0; i < childs.length; i++) {
      if (childs[i].nodeType == 3 && childs[i].nodeValue == startNode)
        s = childs[i];
    }
  } else {
    s = startNode;
  }
  //判断原来的选区是不是由文本节点结束,分开处理
  if (endIsText) {
    let childs = eP.childNodes;
    for (let i = 0; i < childs.length; i++) {
      if (childs[i].nodeType == 3 && childs[i].nodeValue == endNode)
        e = childs[i];
    }
  } else {
    e = startNode;
  }
  //重新构造选区并显示
  let range = document.createRange();
  range.setStart(s, startOffset);
  range.setEnd(e, endOffset);

  let sel = window.getSelection();
  sel.removeAllRanges();
  sel.addRange(range);
}

function use(obj) {
  //定位开始节点
  let sP = findEle(obj.startTagName, obj.startHTML);
  //定位结束节点
  let eP = findEle(obj.endTagName, obj.endHTML);
  show(
    obj,
    sP,
    eP
  );
}
//获取localStorage里存储的选区数据
let a = window.localStorage.getItem("r");
//调用函数显示
use(JSON.parse(a));

大概就是这样,求采纳

Lv4 码徒
朱***叶 UI设计师 6年前#2

可以存在session里,然后在js中获取这个session的值,进行后续的操作,如高亮等

Lv6 码匠
貪***续 PHP开发工程师 6年前#3
我们遇到的难题是:当用户离开后,再次打开这个页面时,我们如何定位回去这个节点node。(已知:网页的节点不会变化,因为我们缓存的)

结构不变的情况下,XPATH 就是标识啊, jQuery 的 selector 也一样。

 文明上网,理性发言!   😉 阿里云幸运券,戳我领取