JavaScript根据选择器字符串判断当前元素是否与选择器匹配

编写一个 match 函数。它接受两个参数,第一个参数是一个选择器字符串性质,第二个是一个 HTML 元素。这个元素你可以认为它一定会在一棵 DOM 树里面。通过选择器和 DOM 元素来判断,当前的元素是否能够匹配到我们的选择器。(不能使用任何内置的浏览器的函数,仅通过 DOM 的 parent 和 children 这些 API,来判断一个元素是否能够跟一个选择器相匹配。)以下是一个调用的例子。

<div id="id1" class="class1">
  <div id='id2' class='class2 class3'>
    <div id='id3' class='class4 class5 class6'></div>
  </div>
</div>
function match(selector, element) {
  let selector_arr = selector.split(' ');//获取element层级
  let parent_arr = [];//用于保存父节点
  let selector_re = /(\w+)|(\.\w+)|(\#\w+)/g;
  for(let i = 0; i < selector_arr.length; i++){
    parent_arr.push(selector_arr[i].match(selector_re));
  }
  
  let matched = true;
  //从当前节点开始向上循环
  for (let j = parent_arr.length-1;j>=0;j--){
    if(!currentElementMatch(parent_arr[j], element)){
      matched = false;
      break;
    }
    element = element.parentNode;
  }
  return matched;
}

function currentElementMatch(currSelector, currElement){
  let hasId = false, hasClass = false, hasTag = false;
  let idMatch = false, classMatch = false, tagMatch = false;
  for(let i = 0; i<currSelector.length;i++;){
    if(currSelector[i].charAt(0) === '#'){
      hasId = true;
      if(currElement.id === currSelector[i].replace('#','')){
        idMatch = true;
      }
    }else if(currSelector[i].charAt(0) === '.'){
      hasClass = true;
      classMatch = false;//因为class可能有多个,所以没判断一个class这里都要先置为false
      for(let j = 0;j<currElement.classList.length; j++){
        if(currElement.classList[j] === currSelector[i].replace('.','')){
          classMatch = true;
          break;
        }
      }
    }else{
      hasTag = true;
      if(currElement.tagName.toLowerCase() === currSelector[i]){
        tagMatch = true;
      }
    }
  }
  return ((hasId && idMatch) || !hasId) && ((hasClass && classMatch) || !hasClass) && ((hasTag && tagMatch) || !hasTag)
}


match("#id1.class1 div.class2.class3 div#id3.class4.class5.class6", document.getElementById("id3"));

猜你喜欢

转载自blog.csdn.net/lixiaosenlin/article/details/108297498
今日推荐