javascript获取元素唯一选择器

neo*_*Dev 1 javascript

我正在使用JavaScript移动元素,我需要为拖放期间发生的组合创建逻辑

我正在尝试从元素中获取详细信息,像选择器这样的CSS也可以,但是如果可能的话,则不建议使用..(例如chrome开发工具中的复制选择器)

document.onmouseup = function(e){
    targetDest = e.target;
    //console.log('targetDest: ', targetDest);

    let 
    indexA = Array.from(targetCurr.parentNode.children).indexOf(targetCurr),
    indexB = Array.from(targetDest.parentNode.children).indexOf(targetDest);

    console.log(indexA, indexB);


    if(targetDest != targetCurr){
        if(targetDest == document.documentElement){
            console.log('document');
        }
        else if(targetDest == undefined){
            console.log('undefined');
        }
        else if(!targetDest){
            console.log('!dest');
        }
        else if(targetDest == null){
            console.log('null');
        }
        else if(targetDest == false){
            console.log('false');
        }
        else{
            console.log('else');
            //targetCurr.parentNode.insertBefore(targetDest, targetCurr);

            //console.log('...');
        }
    }else{
        console.log('itself');
    }


}
Run Code Online (Sandbox Code Playgroud)

mik*_*qex 12

我的解决方案使用:nth-child

function getSelector(elm)
{
if (elm.tagName === "BODY") return "BODY";
const names = [];
while (elm.parentElement && elm.tagName !== "BODY") {
    if (elm.id) {
        names.unshift("#" + elm.getAttribute("id")); // getAttribute, because `elm.id` could also return a child element with name "id"
        break; // Because ID should be unique, no more is needed. Remove the break, if you always want a full path.
    } else {
        let c = 1, e = elm;
        for (; e.previousElementSibling; e = e.previousElementSibling, c++) ;
        names.unshift(elm.tagName + ":nth-child(" + c + ")");
    }
    elm = elm.parentElement;
}
return names.join(">");
}

var qStr = getSelector(document.querySelector("div.moo"));
alert(qStr);
Run Code Online (Sandbox Code Playgroud)
body
<div class="outer">
  div.outer
  <div class="inner" id="foo">
    div#foo.inner
    <div class="moo man">
      div.moo.man
    </div>
  </div>
</div>
Run Code Online (Sandbox Code Playgroud)

请注意,如果其中包含带有 ID 的元素,它不会返回整个路径 - 每个 ID 在页面上都应该是唯一的,因为有效的 HTML 要求如此。

document.querySelector我稍后在代码中使用此函数的输出,因为我需要将焦点返回到replaceChild其父元素之后的同一元素。

我希望 CollinD 不会介意我借用了他的代码片段标记:-)


Kév*_*ier 8

我混合了建议的两种解决方案,以获得人类可读的结果,并且如果有几个相似的兄弟姐妹,则给出正确的元素:

function elemToSelector(elem) {
  const {
    tagName,
    id,
    className,
    parentNode
  } = elem;

  if (tagName === 'HTML') return 'HTML';

  let str = tagName;

  str += (id !== '') ? `#${id}` : '';

  if (className) {
    const classes = className.split(/\s/);
    for (let i = 0; i < classes.length; i++) {
      str += `.${classes[i]}`;
    }
  }

  let childIndex = 1;

  for (let e = elem; e.previousElementSibling; e = e.previousElementSibling) {
    childIndex += 1;
  }

  str += `:nth-child(${childIndex})`;

  return `${elemToSelector(parentNode)} > ${str}`;
}

Run Code Online (Sandbox Code Playgroud)

测试:

// Select an element in Elements tab of your navigator Devtools, or replace $0

document.querySelector(elemToSelector($0)) === $0 &&
document.querySelectorAll(elemToSelector($0)).length === 1
Run Code Online (Sandbox Code Playgroud)

这可能会给你一些类似的东西,它有点长,但它是可读的并且总是有效的:

HTML > BODY:nth-child(2) > DIV.container:nth-child(2) > DIV.row:nth-child(2) > DIV.col-md-4:nth-child(2) > DIV.sidebar:nth-child(1) > DIV.sidebar-wrapper:nth-child(2) > DIV.my-4:nth-child(1) > H4:nth-child(3)
Run Code Online (Sandbox Code Playgroud)

编辑:我刚刚找到了这个包unique-selector


Col*_*inD 5

请记住,这不一定会唯一标识元素。但是,您可以通过从节点向上遍历并在您所在的元素之前构造这种选择器。您可能会做这样的事情

var generateQuerySelector = function(el) {
      if (el.tagName.toLowerCase() == "html")
          return "HTML";
      var str = el.tagName;
      str += (el.id != "") ? "#" + el.id : "";
      if (el.className) {
          var classes = el.className.split(/\s/);
          for (var i = 0; i < classes.length; i++) {
              str += "." + classes[i]
          }
      }
      return generateQuerySelector(el.parentNode) + " > " + str;
}

var qStr = generateQuerySelector(document.querySelector("div.moo"));
alert(qStr);
Run Code Online (Sandbox Code Playgroud)
body
<div class="outer">
  div.outer
  <div class="inner" id="foo">
    div#foo.inner
    <div class="moo man">
      div.moo.man
    </div>
  </div>
</div>
Run Code Online (Sandbox Code Playgroud)

除了向用户展示信息之外,我不建议使用太多其他内容。拆分并重新使用部件必定会引起问题。

  • 正如您所提到的,这种方法对于“相似的兄弟姐妹”来说是失败的,例如 ```&lt;li&gt;...&lt;/li&gt;&lt;li&gt;...&lt;/li&gt;&lt;li&gt;...&lt;/li&gt;` ``。解决方案是使用 ```:nth-child(X)``` 代替。 (3认同)