querySelector search immediate children

2019-01-08 13:08发布

I have some jquery-like function:

function(elem) {
    return $('> someselector', elem);
};

The question is how can i do the same with querySelector()?

The problem is > selector in querySelector() requires parent to be explicitly specified. Is there any workaround?

10条回答
\"骚年 ilove
2楼-- · 2019-01-08 13:38

If you know the tag name of the element that you’re looking into, then you can use it in the selector to achieve what you want.

For example if you have a <select> that has <option>s and <optgroups>, and you only want the <option>s that are its immediate children, not the ones inside <optgoups>:

<select>
  <option>iPhone</option>
  <optgroup>
    <option>Nokia</option>
    <option>Blackberry</option>
  </optgroup>
</select>

So, having a reference to the select element, you can — surprisingly — get its immediate children like this:

selectElement.querySelectorAll('select > option')

It seems to work in Chrome, Safari, and Firefox, but didn’t test in IEs. =/

查看更多
欢心
3楼-- · 2019-01-08 13:38

If you want to eventually find direct children (and not e.g. > div > span), you can try Element.matches():

const elems = Array.from(elem.children).filter(e => e.matches('.my-class'))
查看更多
放我归山
4楼-- · 2019-01-08 13:43

That worked for me:

Node.prototype.search = function(selector)
{
    if (selector.indexOf('@this') != -1)
    {
        if (!this.id)
            this.id = "ID" + new Date().getTime(); 
        while (selector.indexOf('@this') != -1)
            selector = selector.replace('@this', '#' + this.id);
        return document.querySelectorAll(selector);
    } else 
        return this.querySelectorAll(selector);
};

you will have to pass the @this keywork before the > when you want to search for immediate children.

查看更多
ゆ 、 Hurt°
5楼-- · 2019-01-08 13:46

You can't. There's no selector that will simulate your starting point.

The way jQuery does it (more because of a way that qsa behaves that is not to their liking), is that they check to see if elem has an ID, and if not, they temporarily add an ID, then create a full selector string.

Basically you'd do:

var sel = '> someselector';
var hadId = true;
if( !elem.id ) {
    hadID = false;
    elem.id = 'some_unique_value';
}

sel = '#' + elem.id + sel;

var result = document.querySelectorAll( sel );

if( !hadId ) {
    elem.id = '';
}

This certainly isn't jQuery code, but from what I remember, it is basically what they do. Not just in this situation, but in any situation where you're running a selector from the context of a nested element.

Source code for Sizzle

查看更多
我只想做你的唯一
6楼-- · 2019-01-08 13:52

The following is a simplified, generic method for running any CSS selector query over only direct children - it also accounts for combined queries, like "foo[bar], baz.boo":

var count = 0;
function queryChildren(element, selector) {
  var id = element.id,
      guid = element.id = id || 'query_children_' + count++,
      attr = '#' + guid + ' > ',
      selector = attr + (selector + '').replace(',', ',' + attr, 'g');
  var result = element.parentNode.querySelectorAll(selector);
  if (!id) element.removeAttribute('id');
  return result;
}


*** Example Use ***

queryChildren(someElement, '.foo, .bar[xyz="123"]');
查看更多
手持菜刀,她持情操
7楼-- · 2019-01-08 13:59

Though it's not a full answer, you should keep an eye on the W3C Selector API v.2 which is already available in Google Chrome and Safari 7.x (both desktop and mobile), but as far as I have tested, still not there in Firefox and IE.

function(elem) {
  return elem.querySelectorAll(':scope > someselector');
};
查看更多
登录 后发表回答