如何从 jQuery 对象中获取选择器

Posted

技术标签:

【中文标题】如何从 jQuery 对象中获取选择器【英文标题】:How can I get selector from jQuery object 【发布时间】:2011-01-26 03:09:15 【问题描述】:
$("*").click(function()
    $(this); // how can I get selector from $(this) ?
);

有没有一种简单的方法可以$(this)获取选择器?有一种方法可以通过选择器来选择一个元素,但是从元素中获取选择器呢

【问题讨论】:

只是好奇为什么这会有用?您在这里所说的(语义上)是针对每个引用为 $(this) 的元素...元素本身是 $(this) 因此不需要选择器。你已经得到了对象...... 您是否意识到带有嵌套元素的点击会返回多个? div in a body 等,还是我此时太累了? 如果你能描述你想要完成的事情的“最终目标”会很有帮助。这样你可能会得到更好的帮助。 一个元素可以通过多种不同的方式选择。此外,选择器!== 路径。您希望如何处理这些信息? 如果您已经找到了一个 JQuery 元素,并且正在使用插件/模块/子例程,这需要选择器才能工作(可能超出您的控制),这可能很有用。 【参考方案1】:

好的,所以在提问者Fidilip 上方的评论中说,他/她真正追求的是获取当前元素的路径。

这是一个脚本,它将“爬上”DOM 祖先树,然后构建相当具体的选择器,包括单击的项目上的任何 idclass 属性。

在 jsFiddle 上查看它:http://jsfiddle.net/Jkj2n/209/

<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<script>
    $(function() 
        $("*").on("click", function(e) 
          e.preventDefault();
          var selector = $(this)
            .parents()
            .map(function()  return this.tagName; )
            .get()
            .reverse()
            .concat([this.nodeName])
            .join(">");

          var id = $(this).attr("id");
          if (id)  
            selector += "#"+ id;
          

          var classNames = $(this).attr("class");
          if (classNames) 
            selector += "." + $.trim(classNames).replace(/\s/gi, ".");
          

          alert(selector);
      );
    );
    </script>
</head>
<body>
<h1><span>I love</span> jQuery</h1>
<div>
  <p>It's the <strong>BEST THING</strong> ever</p>
  <button id="myButton">Button test</button>
</div>
<ul>
  <li>Item one
    <ul>
      <li id="sub2" >Sub one</li>
      <li id="sub2" class="subitem otherclass">Sub two</li>
    </ul>
  </li>
</ul>
</body>
</html>

例如,如果您要单击下面 HTML 中的第二个列表嵌套列表项,您将得到以下结果:

HTML&gt;BODY&gt;UL&gt;LI&gt;UL&gt;LI#sub2.subitem.otherclass

【讨论】:

谢谢!我将使用您的代码对连接进行一次修改...join(" &gt; ");,将为我提供直系子女,从而获得更严格的路径。 FANTASTIC...我要把它用于我的 chrome 扩展。只是一件事,有时 id 使用冒号 ':' 前缀,我们可以用 '\\:' 替换它 好电话@nonsensickle。我更新了我的示例,并删除了一个 if 语句。 上面的代码片段不返回 SVG 对象的类。这是一个适用于 SVG 的 jsFiddle:http://jsfiddle.net/mikemsq/vbykja4x/7/.【参考方案2】:

::WARNING:: .selector 自 1.7 版起已弃用,自 1.9 版起已删除

昨天在挖掘它的代码时,我看到了 jQuery 对象有一个选择器属性。不知道它是否在文档中定义是多么可靠(用于将来的校对)。但它有效!

$('*').selector // returns *

编辑:如果您要在事件中找到选择器,那么理想情况下,该信息应该是事件本身而不是元​​素的一部分,因为一个元素可以通过各种选择器分配多个点击事件。一种解决方案是使用包装器围绕bind()click() 等添加事件,而不是直接添加。

jQuery.fn.addEvent = function(type, handler) 
    this.bind(type, 'selector': this.selector, handler);
;

选择器作为一个名为selector 的对象属性传递。以event.data.selector 访问它。

让我们在一些标记上尝试一下 (http://jsfiddle.net/DFh7z/):

<p class='info'>some text and <a>a link</a></p>​

$('p a').addEvent('click', function(event) 
    alert(event.data.selector); // p a
);

免责声明:请记住,与 live() 事件一样,如果使用 DOM 遍历方法,则选择器属性可能无效。

<div><a>a link</a></div>

下面的代码将不起作用,因为live 依赖于选择器属性 在这种情况下是 a.parent() - 一个无效的选择器。

$('a').parent().live(function()  alert('something'); );

我们的addEvent 方法会触发,但您也会看到错误的选择器 - a.parent()

【讨论】:

我认为这是我们从 jquery 中得到的最好的东西 =)。也许我稍后会找到完整的解决方案。无论如何,这真的很方便,谢谢! =) @MarkoDumic:一定已经被弃用了。该链接现已失效,点击它只会告诉我们:No Such jQuery Method Exists @Levitikon 你真的否决了三年前的答案,因为现在它已被弃用吗?!您确实应该编辑答案并发出警告【参考方案3】:

与@drzaus 合作,我们提出了以下 jQuery 插件。

jQuery.getSelector

!(function ($, undefined) 
    /// adapted http://jsfiddle.net/drzaus/Hgjfh/5/

    var get_selector = function (element) 
        var pieces = [];

        for (; element && element.tagName !== undefined; element = element.parentNode) 
            if (element.className) 
                var classes = element.className.split(' ');
                for (var i in classes) 
                    if (classes.hasOwnProperty(i) && classes[i]) 
                        pieces.unshift(classes[i]);
                        pieces.unshift('.');
                    
                
            
            if (element.id && !/\s/.test(element.id)) 
                pieces.unshift(element.id);
                pieces.unshift('#');
            
            pieces.unshift(element.tagName);
            pieces.unshift(' > ');
        

        return pieces.slice(1).join('');
    ;

    $.fn.getSelector = function (only_one) 
        if (true === only_one) 
            return get_selector(this[0]);
         else 
            return $.map(this, function (el) 
                return get_selector(el);
            );
        
    ;

)(window.jQuery);

精简的 javascript

// http://***.com/questions/2420970/how-can-i-get-selector-from-jquery-object/15623322#15623322
!function(e,t)var n=function(e)var n=[];for(;e&&e.tagName!==t;e=e.parentNode)if(e.className)var r=e.className.split(" ");for(var i in r)if(r.hasOwnProperty(i)&&r[i])n.unshift(r[i]);n.unshift(".")if(e.id&&!/\s/.test(e.id))n.unshift(e.id);n.unshift("#")n.unshift(e.tagName);n.unshift(" > ")return n.slice(1).join("");e.fn.getSelector=function(t)if(true===t)return n(this[0])elsereturn e.map(this,function(e)return n(e))(window.jQuery)

用法和陷阱

<html>
    <head>...</head>
    <body>
        <div id="sidebar">
            <ul>
                <li>
                    <a href="/" id="home">Home</a>
                </li>
            </ul>
        </div>
        <div id="main">
            <h1 id="title">Welcome</h1>
        </div>

        <script type="text/javascript">

            // Simple use case
            $('#main').getSelector();           // => 'HTML > BODY > DIV#main'

            // If there are multiple matches then an array will be returned
            $('body > div').getSelector();      // => ['HTML > BODY > DIV#main', 'HTML > BODY > DIV#sidebar']

            // Passing true to the method will cause it to return the selector for the first match
            $('body > div').getSelector(true);  // => 'HTML > BODY > DIV#main'

        </script>
    </body>
</html>

带有 QUnit 测试的小提琴

http://jsfiddle.net/CALY5/5/

【讨论】:

我喜欢你要去的地方,所以我做了一些fixes/changes: * jQuery 插件利用 jQuery 实用程序$.map * 可选分隔符(需要去除奇怪的空标签名)* 你不需要在foreach 循环中检查hasOwnProperty 是否安全? 感谢 cmets,本周末我将设置一个合适的测试套件,并努力采纳您的建议。 @drzaus 我已经更新了这个问题。我决定省略您添加的自定义分隔符,因为' &gt; ' 以外的任何分隔符都会导致它不返回元素的选择器。 酷,干得好;以前没见过qunit。我认为分隔符只是为了演示,但现在我知道它是文字选择器路径的一部分。【参考方案4】:

你试过了吗?

 $("*").click(function()
    $(this).attr("id"); 
 );

【讨论】:

尽量不要使用*选择器,太慢了! 这只有在元素有一个 ID 的情况下才有效。【参考方案5】:

试试这个:

$("*").click(function(event)
    console.log($(event.handleObj.selector));
 );

【讨论】:

【参考方案6】:

我发布了一个jQuery插件:jQuery Selectorator,你可以像这样得到选择器。

$("*").on("click", function()
  alert($(this).getSelector().join("\n"));
  return false;
);

【讨论】:

这是处理克隆兄弟的唯一方法,谢谢!【参考方案7】:

好吧,我写了这个简单的 jQuery 插件。

这会检查 id 或类名,并尝试提供尽可能准确的选择器。

jQuery.fn.getSelector = function() 

    if ($(this).attr('id')) 
        return '#' + $(this).attr('id');
    

    if ($(this).prop("tagName").toLowerCase() == 'body')    return 'body';

    var myOwn = $(this).attr('class');
    if (!myOwn) 
        myOwn = '>' + $(this).prop("tagName");
     else 
        myOwn = '.' + myOwn.split(' ').join('.');
    

    return $(this).parent().getSelector() + ' ' + myOwn;

【讨论】:

【参考方案8】:

以这种方式在 $ 函数上添加一个层:

$ = (function(jQ)  
	return (function()  
		var fnc = jQ.apply(this,arguments);
		fnc.selector = (arguments.length>0)?arguments[0]:null;
		return fnc; 
	);
)($);

现在你可以做类似的事情

$("a").selector
并且即使在较新的 jQuery 版本上也会返回 "a"。

【讨论】:

这正是我想要的。考虑到我找了多长时间,它的效果非常好!谢谢阿尔伯特。【参考方案9】:

http://www.selectorgadget.com/ 是专门为此用例设计的书签。

也就是说,我同意大多数其他人的观点,即您应该自己学习 CSS 选择器,试图用代码生成它们是不可持续的。 :)

【讨论】:

【参考方案10】:

我为@jessegavin 的修复添加了一些修复。

如果元素上有 ID,这将立即返回。我还添加了一个 name 属性检查和一个 nth-child 选择器,以防元素没有 id、class 或 name。

如果页面上有多个表单并且有类似的输入,则名称可能需要确定范围,但我还没有处理。

function getSelector(el)
    var $el = $(el);

    var id = $el.attr("id");
    if (id)  //"should" only be one of these if theres an ID
        return "#"+ id;
    

    var selector = $el.parents()
                .map(function()  return this.tagName; )
                .get().reverse().join(" ");

    if (selector) 
        selector += " "+ $el[0].nodeName;
    

    var classNames = $el.attr("class");
    if (classNames) 
        selector += "." + $.trim(classNames).replace(/\s/gi, ".");
    

    var name = $el.attr('name');
    if (name) 
        selector += "[name='" + name + "']";
    
    if (!name)
        var index = $el.index();
        if (index) 
            index = index + 1;
            selector += ":nth-child(" + index + ")";
        
    
    return selector;

【讨论】:

【参考方案11】:

即使在上述解决方案之后,我也得到了多个元素,所以我扩展了 dds1024 的工作,以获得更多精确的 dom 元素。

例如DIV:nth-child(1) DIV:nth-child(3) DIV:nth-child(1) ARTICLE:nth-child(1) DIV:nth-child(1) DIV:nth-child(8) DIV: nth-child(2) DIV:nth-child(1) DIV:nth-child(2) DIV:nth-child(1) H4:nth-child(2)

代码:

function getSelector(el)

    var $el = jQuery(el);

    var selector = $el.parents(":not(html,body)")
                .map(function()  
                                    var i = jQuery(this).index(); 
                                    i_str = ''; 

                                    if (typeof i != 'undefined') 
                                    
                                        i = i + 1;
                                        i_str += ":nth-child(" + i + ")";
                                    

                                    return this.tagName + i_str; 
                                )
                .get().reverse().join(" ");

    if (selector) 
        selector += " "+ $el[0].nodeName;
    

    var index = $el.index();
    if (typeof index != 'undefined')  
        index = index + 1;
        selector += ":nth-child(" + index + ")";
    

    return selector;

【讨论】:

【参考方案12】:

考虑到此处阅读的一些答案,我想提出以下建议:

function getSelectorFromElement($el) 
  if (!$el || !$el.length) 
    return ;
  

  function _getChildSelector(index) 
    if (typeof index === 'undefined') 
      return '';
    

    index = index + 1;
    return ':nth-child(' + index + ')';
  

  function _getIdAndClassNames($el) 
    var selector = '';

    // attach id if exists
    var elId = $el.attr('id');
    if(elId)
      selector += '#' + elId;
    

    // attach class names if exists
    var classNames = $el.attr('class');
    if(classNames)
      selector += '.' + classNames.replace(/^\s+|\s+$/g, '').replace(/\s/gi, '.');
    

    return selector;
  

  // get all parents siblings index and element's tag name,
  // except html and body elements
  var selector = $el.parents(':not(html,body)')
    .map(function() 
      var parentIndex = $(this).index();

      return this.tagName + _getChildSelector(parentIndex);
    )
    .get()
    .reverse()
    .join(' ');

  if (selector) 
    // get node name from the element itself
    selector += ' ' + $el[0].nodeName +
      // get child selector from element ifself
      _getChildSelector($el.index());
  

  selector += _getIdAndClassNames($el);

  return selector;

也许对创建一个 jQuery 插件有用?

【讨论】:

5 年后。我在 Cypress 中使用过它 - 页面对象模型。如果其他人需要 Cypress.Chaniable 对象的选择器,请在此处注意。只需要将 $(this) 替换为 Cypress。$(this) 其余的都可以。【参考方案13】:

这可以获得点击的 HTML 元素的选择器路径-

 $("*").on("click", function() 

    let selectorPath = $(this).parents().map(function () return this.tagName;).get().reverse().join("->");

    alert(selectorPath);

    return false;

);

【讨论】:

【参考方案14】:

您是否试图获取被点击的当前标签的名称?

如果是这样,请执行此操作..

$("*").click(function()
    alert($(this)[0].nodeName);
);

您无法真正获得“选择器”,您的情况下的“选择器”是*

【讨论】:

我不需要标签名称。我只需要我点击的元素的路径。 啊,开始到达某个地方“元素的路径”与“选择器”有很大不同。所以你需要这个元素,以及它所有的父节点名称? 我发布了另一个答案,它更接近您的实际目标。您应该编辑问题,使其更具体。【参考方案15】:

相同的Javascript代码,以防任何人需要,因为我需要它。这只是上述所选答案的翻译。

    <script type="text/javascript">

function getAllParents(element)
    var a = element;
    var els = [];
    while (a && a.nodeName != "#document") 
        els.unshift(a.nodeName);
        a = a.parentNode;
    
    return els.join(" ");


function getJquerySelector(element)

    var selector = getAllParents(element);
    /* if(selector)
        selector += " " + element.nodeName;
     */
    var id = element.getAttribute("id");
    if(id)
        selector += "#" + id;
    
    var classNames = element.getAttribute("class");
    if(classNames)
        selector += "." + classNames.replace(/^\s+|\s+$/g, '').replace(/\s/gi, ".");
    
    console.log(selector);
    alert(selector);
    return selector;

</script>

【讨论】:

【参考方案16】:

谢谢 p1nox!

我的问题是将注意力重新放在修改部分表单的 ajax 调用上。

$.ajax(  url : "ajax_invite_load.php",
        async : true,
         type : 'POST',
         data : ...
     dataType : 'html',
      success : function(html, statut) 
                    var focus = $(document.activeElement).getSelector();
                    $td_left.html(html);
                    $(focus).focus();
                
);

我只需要将你的函数封装在一个 jQuery 插件中:

    !(function ($, undefined) 

    $.fn.getSelector = function () 
      if (!this || !this.length) 
        return ;
      

      function _getChildSelector(index) 
        if (typeof index === 'undefined') 
          return '';
        

        index = index + 1;
        return ':nth-child(' + index + ')';
      

      function _getIdAndClassNames($el) 
        var selector = '';

        // attach id if exists
        var elId = $el.attr('id');
        if(elId)
          selector += '#' + elId;
        

        // attach class names if exists
        var classNames = $el.attr('class');
        if(classNames)
          selector += '.' + classNames.replace(/^\s+|\s+$/g, '').replace(/\s/gi, '.');
        

        return selector;
      

      // get all parents siblings index and element's tag name,
      // except html and body elements
      var selector = this.parents(':not(html,body)')
        .map(function() 
          var parentIndex = $(this).index();

          return this.tagName + _getChildSelector(parentIndex);
        )
        .get()
        .reverse()
        .join(' ');

      if (selector) 
        // get node name from the element itself
        selector += ' ' + this[0].nodeName +
          // get child selector from element ifself
          _getChildSelector(this.index());
      

      selector += _getIdAndClassNames(this);

      return selector;
    

)(window.jQuery);

【讨论】:

【参考方案17】:

这不会向您显示 DOM 路径,但会在查看对象时输出您在例如 chrome 调试器中看到的内容的字符串表示形式。

$('.mybtn').click( function(event)
    console.log("%s", this);    // output: "button.mybtn"
);

https://developer.chrome.com/devtools/docs/console-api#consolelogobject-object

【讨论】:

【参考方案18】:

怎么样:

var selector = "*"
$(selector).click(function() 
    alert(selector);
);

我不相信 jQuery 存储使用的选择器文本。毕竟,如果您这样做,那将如何工作:

$("div").find("a").click(function() 
    // what would expect the 'selector' to be here?
);

【讨论】:

jQuery 在内部构建选择器$('div').find('a').selectordiv a。如果事件不是通过 jQuery 函数创建的,而是通过包装器创建的,我相信选择器可以作为数据参数传递给事件处理程序。 这真的是一个严肃的答案吗?【参考方案19】:

最好的答案是

var selector = '#something';

$(selector).anything(function()
  console.log(selector);
);

【讨论】:

这似乎根本不是最佳答案。

以上是关于如何从 jQuery 对象中获取选择器的主要内容,如果未能解决你的问题,请参考以下文章

jQuery 日期选择器。我如何从 Jquery datepicker 中获取年份

如何从 jQuery 选择器中获取 DOM 元素?

使用 Jquery 在选择器的结果中搜索

从 JQUERY 日期选择器中获取价值

jQuery选择器

jQuery选择器基础入门教程