聊聊 CSS 选择器

来源:互联网 发布:淘宝刷lol裁决靠谱吗 编辑:程序博客网 时间:2024/06/05 08:57

聊聊 CSS 选择器

firefox 开发者工具有一个很酷的功能:在查看器中右键单击某元素,选择“复制唯一选择器”,刻意复制定位至该元素的唯一选择器。这跟 CSS 选择器的功能恰好相反,可以视作 document.querySelector 的逆运算。

这个功能 firefox 怎么实现的呢? grep 源码,追踪到 browser/devtools/inspector/inspector-panel.js 文件中下列代码:

/** * Copy a unique selector of the selected Node to the clipboard. */function InspectorPanel_copyUniqueSelector() {    if (!this.selection.isNode()) {        return;    }    let toCopy = CssLogic.findCssSelector(this.selection.node);    if (toCopy) {        clipboardHelper.copyString(toCopy);    }}

根据 CssLogic 又跟踪到 toolkit/devtools/styleinspector/css-logic.js 文件:

/** * Find a unique CSS selector for a given element * @returns a string such that ele.ownerDocument.querySelector(reply) === ele * and ele.ownerDocument.querySelectorAll(reply).length === 1 */CssLogic.findCssSelector = function CssLogic_findCssSelector(ele) {  ele = LayoutHelpers.getRootBindingParent(ele);  var document = ele.ownerDocument;  if (!document || !document.contains(ele)) {    throw new Error('findCssSelector received element not inside document');  }  // document.querySelectorAll("#id") returns multiple if elements share an ID  if (ele.id && document.querySelectorAll('#' + CSS.escape(ele.id)).length === 1) {    return '#' + CSS.escape(ele.id);  }  // Inherently unique by tag name  var tagName = ele.localName;  if (tagName === 'html') {    return 'html';  }  if (tagName === 'head') {    return 'head';  }  if (tagName === 'body') {    return 'body';  }  // We might be able to find a unique class name  var selector, index, matches;  if (ele.classList.length > 0) {    for (var i = 0; i < ele.classList.length; i++) {      // Is this className unique by itself?      selector = '.' + CSS.escape(ele.classList.item(i));      matches = document.querySelectorAll(selector);      if (matches.length === 1) {        return selector;      }      // Maybe it's unique with a tag name?      selector = tagName + selector;      matches = document.querySelectorAll(selector);      if (matches.length === 1) {        return selector;      }      // Maybe it's unique using a tag name and nth-child      index = positionInNodeList(ele, ele.parentNode.children) + 1;      selector = selector + ':nth-child(' + index + ')';      matches = document.querySelectorAll(selector);      if (matches.length === 1) {        return selector;      }    }  }  // Not unique enough yet.  As long as it's not a child of the document,  // continue recursing up until it is unique enough.  if (ele.parentNode !== document) {    index = positionInNodeList(ele, ele.parentNode.children) + 1;    selector = CssLogic_findCssSelector(ele.parentNode) + ' > ' +            tagName + ':nth-child(' + index + ')';  }  return selector;};
0 0