Oct1a

根据网页内容查找dom元素进行操作的四种方式

比如网页有倒计时功能,只有倒计时结束按钮才出来,这个时候需要js快速进行判断点击,已知条件只有按钮文本的情况下,要进行代码实现。

image-20210816105438610

<body>
    <div class="child-1">
        <div class="child-1-1">
            <div class="child-1-1-1">
                <button>
                    确定
                </button>
            </div>
        </div>
    </div>
    <div class="child-2">
        <div class="child-2-1">
            A
        </div>
        <div class="child-2-2">
            <button>
                联系我们
            </button>
        </div>
    </div>
</body>

比如目前有个需求是只知道按钮文字—“确定”,不确定dom结构以及class、id的情况下,需要对元素进行点击操作。

方式一,遍历

一开始是想遍历节点,但需要深层遍历dom节点才行,用深层遍历节点判断标签与文本内容是否符合,如果一致则取该节点来进行操作。但这个会有性能问题,不能一直计时器挂着遍历吧。

上面的dom结构其实很像二叉树,可以简化成下图这样:

img

二叉树遍历的方式可以分为两种,深度优先遍历广度优先遍历

深度优先遍历 顺序: 1 2 4 5 7 8 3 6 (二叉树中又叫做先序遍历)
广度优先遍历 顺序:1 2 3 4 5 6 7 8 (二叉树中又叫做层级遍历)

深度遍历查找

let deepDom = (node,tag,text,result=[])=>{
    if (node) {
        let children = node.children;
        for (let i = 0; i < children.length; i++) {
            if(children[i].children.length!=0){ //如果还有子节点则继续递归
                deepDom(children[i],tag,text,result);
            }else if(children[i].tagName == tag.toUpperCase() && children[i].innerText == text){
                result.push(children[i])
            }
        }
    }
    return result
}

let result_list = deepDom(document.querySelector("body"),"button","按钮的文本") //如果有相同需求,改变后面两个参数即可
result_list[0].click() //如果出现多个相同的情况下再另行判断即可

广度遍历查找

let widthDeepDoom=(node,tag,text)=>{
    let stack=[];
    let result = []
    if(node){
        stack.push(node); //压入栈
        while(stack.length){
            let item=stack.shift(); // 删除数组中的第一个元素 并且返回
            let children=item.children;
            for(let i=0;i<children.length;i++){
                if(children[i].children.length!=0){
                     stack.push(children[i])
                }else if(children[i].tagName == tag.toUpperCase() && children[i].innerText == text){
                    // result.push(children[i])
                     result = children[i]
                }
            }
        }
    }
    return result
}

let result_list = widthDeepDoom(document.querySelector("body"),"button","按钮的文本") //如果有相同需求,改变后面两个参数即可
result_list.click() //点击按钮

方式二,正则

使用正则表达式进行匹配,直接匹配所需的节点信息

let regexpDom = (tag,text)=>{
  let reg = new RegExp(`<${tag} .*>${text}<\/${tag}>`, "gi");
  return Array.prototype.slice.call(document.querySelectorAll(tag)).filter(function(element) {
    var match = element.outerHTML.match(reg);
    if (match == null) {
      return false;
    }
    if (match == void 0) {
      return false;
    }
    return true;
  })
}
let result_list = regexpDom('button','登录')
result_list[0].click()

参考文档 : how to access DOM elements using javascript Regex - Stack Overflow

方式三,Jquery

使用jquery的选择器,该选择器可以选取包含指定字符串的元素。

$(":button:contains('按钮的文本')")

这种情况的话,需要网站自带Jquery,否则需要自行添加jq地址进行引用

if(typeof jQuery=="undefined"){
    script=document.createElement("script");
    script.setAttribute("charset","utf-8");
    script.src="http://code.jquery.com/jquery-migrate-1.2.1.min.js";
    document.head.appendChild(script);
  }

方式四,xpath

目前感觉最好的一种匹配方式,xpath

  let matchDOM = document.evaluate("//button[contains(., '按钮的文本')]", document, null, XPathResult.ANY_TYPE, null );
  let thisHeading = matchDOM.iterateNext();
  if(thisHeading) thisHeading.click();

本作品采用 知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议 进行许可。