Использование querySelectorAll для извлечения прямых детей

Я могу это сделать:

<div id="myDiv">
   <div class="foo"></div>
</div>
myDiv = getElementById("myDiv");
myDiv.querySelectorAll("#myDiv > .foo");

То есть, я могу успешно получить все прямые дочерние myDivэлементы, имеющие класс .foo.

Проблема в том, что меня беспокоит, что я должен включать #myDivв myDivector, потому что я выполняю запрос на #myDivэлементе (поэтому он явно избыточен).

Я должен быть в состоянии оставить >, но селектор не является законным синтаксисом, так как он начинается с .querySelectorAll.

Кто-нибудь знает, как написать селектор, который получает только прямые дочерние элементы элемента, на котором работает селектор?

javascript,dom,css-selectors,

64

Ответов: 10


29 принят

Хороший вопрос, но, как вы видите, нет способа сделать «комбинаторные корневые запросы», как их называет Джон Ресиг .

Однако в некоторых случаях вы можете просто пропустить myDiv.childrenи использовать другие хорошие старомодные функции DOM API. Вместо неподдерживаемых myDiv.getElementsByClassName("foo")вы можете просто написать .parentNode === myDiv, например.

К сожалению, я не могу придумать способ справиться с ситуацией без добавления дополнительной пользовательской логики фильтра (например, найти :scopeчей ) и, очевидно, не идеально, если вы пытаетесь поддерживать один путь кода, который действительно просто хочет взять произвольную селекторную строку как ввод и список совпадений в качестве вывода! Но, если я, как и я, вы в конечном итоге задали этот вопрос просто потому, что вы застряли в мысли «все, что у вас было, это молоток», не забудьте, что есть множество других инструментов, предлагаемых DOM.var myDiv = getElementById("myDiv"); var fooEls = myDiv.querySelectorAll(":scope > .foo");


79 ов

Кто-нибудь знает, как написать селектор, который получает только прямые дочерние элементы элемента, на котором работает селектор?

Правильный способ записи селектора, который «привязан» к текущему элементу, должен использоваться querySelector.

querySelectorAll

Однако поддержка браузера ограничена, и вам понадобится прокладка, если вы хотите ее использовать. Для этой цели я построил scopedQuerySelectorShim .

Примечание . :scopeПсевдокласс был устаревшим. Однако он по-прежнему поддерживается в querySelector/ var count = 0 ; function queryChildren ( элемент , селектор ) { var id = element . id , guid = элемент . id = id || 'query_children_' + count ++, attr = '#' + guid + '>' , селектор = attr + ( селектор + '' ). replace ( ',' , ',' + attr , 'g' ); var result = element . parentNode . querySelectorAll ( селектор ); если (! ID ) элемент . removeAttribute ( 'id' ); результат возврата ; } "rel =" noreferrer "> querySelectorAll .


4

Вот гибкий метод, написанный в vanilla JS, который позволяет запускать запрос выбора CSS только для прямых дочерних элементов элемента:

myDiv.parentElement.querySelectorAll("#myDiv > .foo");

2

если вы точно знаете, что элемент уникален (например, ваш случай с идентификатором):

function getDirectChildren(elm, sel){
    var ret = [], i = 0, l = elm.childNodes.length;
    for (var i; i < l; ++i){
        if (elm.childNodes[i].matchesSelector(sel)){
            ret.push(elm.childNodes[i]);
        }
    }
    return ret;
}

Для более «глобального» решения: (используйте matchSelector shim )

elm

где selваш родительский элемент, и selваш селектор. Может быть полностью использован как прототип.


1

Я создал функцию для обработки этой ситуации, подумал, что поделюсь ею.

getDirectDecendent(elem, selector, all){
    const tempID = randomString(10) //use your randomString function here.
    elem.dataset.tempid = tempID;

    let returnObj;
    if(all)
        returnObj = elem.parentElement.querySelectorAll(`[data-tempid="${tempID}"] > ${selector}`);
    else
        returnObj = elem.parentElement.querySelector(`[data-tempid="${tempID}"] > ${selector}`);

    elem.dataset.tempid = '';
    return returnObj;
}

По сути дела, вы создаете случайную строку (функция randomString здесь - это импортированный модуль npm, но вы можете сделать свой собственный.), Затем используя эту случайную строку, чтобы гарантировать, что вы получите элемент, который вы ожидаете в селекторе. Тогда вы можете использовать >после этого.

Причина, по которой я не использую атрибут id, заключается в том, что атрибут id уже может использоваться, и я не хочу его переопределять.

JavaScript, дом, CSS-селекторов,
Похожие вопросы