querySelectorAll을 사용하여 직계 자식 검색
나는 이것을 할 수있다 :
<div id="myDiv">
<div class="foo"></div>
</div>
myDiv = getElementById("myDiv");
myDiv.querySelectorAll("#myDiv > .foo");
즉, myDiv
class 가있는 요소 의 모든 직계 자식을 성공적으로 검색 할 수 있습니다 .foo
.
문제는 요소 #myDiv
에 대한 쿼리를 실행하고 있기 때문에 선택자 에을 포함해야한다는 myDiv
점입니다 (분명히 중복 됨).
나는 #myDiv
꺼둘 수 있어야 하지만 선택자는 >
.
누구든지 선택기가 실행되는 요소의 직접 자식을 얻는 선택자를 작성하는 방법을 알고 있습니까?
좋은 질문. 요청을 받았을 당시 "결합 자 기반 쿼리"( John Resig가 호출 한 쿼리)를 수행하는 보편적으로 구현 된 방법 은 존재하지 않았습니다.
이제 : scope 의사 클래스가 도입되었습니다. 그것은되지 지원 에지 또는 IE의 [중고 Chrominum] 버전에 있지만, 이미 몇 년 동안 사파리에서 지원하고있다. 이를 사용하면 코드가 다음과 같이 될 수 있습니다.
let myDiv = getElementById("myDiv");
myDiv.querySelectorAll(":scope > .foo");
어떤 경우에는 .querySelectorAll
다른 좋은 구식 DOM API 기능을 건너 뛰고 사용할 수도 있습니다. 예를 들어, 대신에 myDiv.querySelectorAll(":scope > *")
를 쓸 수 있습니다 myDiv.children
.
그렇지 않으면 아직 의존 할 수 :scope
없다면 더 많은 사용자 정의 필터 논리 (예 : find myDiv.getElementsByClassName("foo")
who .parentNode === myDiv
) 를 추가하지 않고 상황을 처리하는 다른 방법을 생각할 수 없으며 실제로 하나의 코드 경로를 지원하려는 경우 이상적이지 않습니다. 임의의 선택기 문자열을 입력으로 사용하고 일치 목록을 출력으로 사용하려고합니다! 나처럼 당신이 붙어 생각을 가지고 있기 때문에 단순히이 질문을 결국하지만 다양한있다 잊지 마세요 "당신이 가진 모든 망치이었다" 다른 DOM을 제공 너무 도구.
누구든지 선택기가 실행되는 요소의 직접 자식을 얻는 선택자를 작성하는 방법을 알고 있습니까?
현재 요소에 "루팅 된"선택기를 작성하는 올바른 방법은를 사용하는 것 :scope
입니다.
var myDiv = getElementById("myDiv");
var fooEls = myDiv.querySelectorAll(":scope > .foo");
그러나 브라우저 지원은 제한적 이며 사용하려면 shim이 필요합니다. 이 목적으로 scopedQuerySelectorShim 을 만들었 습니다 .
다음은 바닐라 JS로 작성된 유연한 메서드로, 요소의 직접 자식에 대해서만 CSS 선택기 쿼리를 실행할 수 있습니다.
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;
}
요소가 고유한지 확인하는 경우 (예 : ID가있는 케이스) :
myDiv.parentElement.querySelectorAll("#myDiv > .foo");
보다 "글로벌"솔루션 : ( matchsSelector shim 사용 )
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;
}
elm
부모 요소는 어디에 sel
있고 선택자는 있습니다. 프로토 타입으로도 사용할 수 있습니다.
이 상황을 처리하는 함수를 만들었고 공유 할 것이라고 생각했습니다.
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;
}
In essence what you are doing is generating a random-string (randomString function here is an imported npm module, but you can make your own.) then using that random string to guarantee that you get the element you are expecting in the selector. Then you are free to use the >
after that.
The reason I am not using the id attribute is that the id attribute may already be used and I don't want to override that.
The following solution is different to the ones proposed so far, and works for me.
The rationale is that you select all matching children first, and then filter out the ones which are not direct children. A child is a direct child if it does not have a matching parent with the same selector.
function queryDirectChildren(parent, selector) {
const nodes = parent.querySelectorAll(selector);
const filteredNodes = [].slice.call(nodes).filter(n =>
n.parentNode.closest(selector) === parent.closest(selector)
);
return filteredNodes;
}
HTH!
Well we can easily get all the direct children of an element using childNodes
and we can select ancestors with a specific class with querySelectorAll
, so it's not hard to imagine we could create a new function that gets both and compares the two.
HTMLElement.prototype.queryDirectChildren = function(selector){
var direct = [].slice.call(this.directNodes || []); // Cast to Array
var queried = [].slice.call(this.querySelectorAll(selector) || []); // Cast to Array
var both = [];
// I choose to loop through the direct children because it is guaranteed to be smaller
for(var i=0; i<direct.length; i++){
if(queried.indexOf(direct[i])){
both.push(direct[i]);
}
}
return both;
}
Note: This will return an Array of Nodes, not a NodeList.
Usage
document.getElementById("myDiv").queryDirectChildren(".foo");
I would like to add that you can extend the compatibility of :scope by just assigning a temporary attribute to the current node.
let node = [...];
let result;
node.setAttribute("foo", "");
result = window.document.querySelectorAll("[foo] > .bar");
// And, of course, you can also use other combinators.
result = window.document.querySelectorAll("[foo] + .bar");
result = window.document.querySelectorAll("[foo] ~ .bar");
node.removeAttribute("foo");
I am just doing this without even trying it. Would this work?
myDiv = getElementById("myDiv");
myDiv.querySelectorAll(this.id + " > .foo");
Give it a try, maybe it works maybe not. Apolovies, but I am not on a computer now to try it (responding from my iPhone).
I'd have gone with
var myFoo = document.querySelectorAll("#myDiv > .foo");
var myDiv = myFoo.parentNode;
참고URL : https://stackoverflow.com/questions/3680876/using-queryselectorall-to-retrieve-direct-children
'Programing' 카테고리의 다른 글
React.js에서 onSubmit 설정 (0) | 2020.09.09 |
---|---|
가장 일반적인 Mercurial 명령에 해당하는 Git? (0) | 2020.09.09 |
Vim에서 인코딩 및 파일 인코딩을 utf-8로 설정 (0) | 2020.09.09 |
하위 프로세스 표준 출력을 변수로 파이프 (0) | 2020.09.09 |
iOS 이미지 방향에 이상한 동작이 있습니다. (0) | 2020.09.09 |