浏览器的Web开发者工具为我们提供了许多实用的功能,其中一个最常用的面板是Elements,我们可以其中为元素增加属性,修改元素内容等。而另一个可能不是太多人知道的功能是它可以让我们复制选中元素的CSS选择器,如下图所示:

点击Copy selector菜单之后,会把当前元素的CSS选择器保存在粘贴板中,你可以在你的编辑器粘贴出它的内容,例如:

#question > div.post-layout > div.postcell.post-layout--right > div.post-text > p

你可能会有一个疑问:我们为什么需要得到元素的选择器呢?它有什么用呢?

设想你有个需求:我们想知道网站访客对于页面中哪些部分感兴趣,点击了哪些元素?甚至我们想以热力图的形式来展示页面中的点击分布图。

这时候我们需要知道用户点击了哪个元素,而选择器对于定位元素至关重要。它可以作为元素在网页中的唯一识别符,在现代浏览器中可以使用 querySelector() 方法来选中它们。

上图开发者工具可以方便的提供它的值,遗憾的是它不属于浏览器API的一部分,对于开发者来说想在网页环境中执行,则需要手动实现这个功能。

场景1. 含有 id 属性的元素

场景1. 含有 id 属性的元素

这种是最简单的场景,我们只需要读取元素的id属性值即可。

场景2. 没有 id 属性的元素

场景2. 没有 id 属性的元素

如果一个元素没有id属性,我们就失去了快捷途径。接下来要做的就是逐级向上查询它的父级元素,并得到最终的选择器。我们继续扩展这个函数的功能,如下:

我们简单介绍一下上述代码中的要点:

· #1 我们用了while循环来遍历当前元素的父级元素

· #2 如果元素含有 id 属性,则把id选择器置入数组,循环结束

· #3 如果遍历到达了 body 元素,则把body标签置入数组,循环结束

· #4 这里用了一个 for 循环来查询元素在它父级元素中的位置

· #5 为 element 赋值为它的父级元素,继续向上遍历

· #6 最后把数组结果以 箭头符号连接并返回

上述代码在现代浏览器中工作良好,不过如果你在IE8中运行上述代码,可能会得不到期望的结果。原因在于其中的 previousElementSibling 属性在IE8中不支持。

又是浏览器兼容性问题!如果你不需要兼容IE8,上述代码就已经足够了。如果必须兼容的话,则需要增加更多兼容代码:

我们新增了一个 previousElementSibling 函数,在其中做了浏览器兼容。对于现代浏览器仍会使用 previousElementSibling 属性,对于不支持此属性的浏览器则使用传统的 previousSibling属性并确保元素的类型为一个元素节点。

至此,我们就兼容了所有的浏览器!

场景3 元素含有id属性但需要忽略

场景3 元素含有id属性但需要忽略

文章写到这里,似乎应该结束了,为什么我有时候会需要忽略一个元素的id属性值呢?使用id不是很简单明了吗?

没错,id是最简单易用的方式。不过这一切的前提是页面中的id是稳定可靠的,设想一下如下元素:

上述元素的id属性值中含有空格,是一个无效的id值。使用W3 提供的HTML检查器会提示如下错误:

所以我们的getCssPath() 函数需要增加参数,允许不使用id属性。

此时你调用 getCssPath(document.getElementById("invalid id"), true) 返回的字符串格式是 "body > div:nth-child(4)" ,而不是再是 “#invalid id”。这样,我们就可以使用 document.querySelector ()选中这个元素了。