簡體   English   中英

Vanilla JavaScript 等效於 jQuery(...).parent().nextAll(selector)

[英]Vanilla JavaScript equivalent of jQuery(…).parent().nextAll(selector)

我正在嘗試使用 vanilla JavaScript 選擇器(不使用 jQuery)來獲得如下所示的相同選擇:

$('[data-automationid=pictureupload_1]').parent().nextAll('input[type=text]')

有人可以幫幫我嗎? 我一直在掙扎。

據我所知,DOM 中沒有nextAll方法,因此在不使用 jQuery 的情況下這樣做有點棘手。

我們可以使用生成器來迭代和過濾nextElementSibling如下所示:

function* myNextAll(e, selector) {
   while (e = e.nextElementSibling) {
       if ( e.matches(selector) ) {
          yield e;
       }
   }
}

let e1 = document.querySelector("[data-automationid=pictureupload_1]").parentElement;

let siblings = [...myNextAll(e1, "input[type=text]")];

  • 使用document.querySelector('[data-automationid=pictureupload_1]')選擇起始節點。
  • 使用parentElement.children獲取父節點中的所有兄弟節點(包括父節點本身)。
  • 遍歷兄弟節點,直到建立父節點。
  • 查找所有其他兄弟節點,如果它們是 INPUT 節點並且來自文本類型 (=1)。
  • 將它們收集在一個數組中。

為了演示迭代結果並通過測試類更改背景。

如果你想試試: https : //jsfiddle.net/7p8wt4km/2/

 let result = []; let par = document.querySelector('[data-automationid=pictureupload_1]').parentElement; let sibling = par.parentElement.children; let found = false; for (let i=0; i< sibling.length; i++) { if (!found && sibling[i] ===par) { found = true; continue; } else if (found) { let sib = sibling[i]; if (sib.nodeName !== 'INPUT' || sib.nodeType!= 1) continue; result.push(sib); } } result.forEach(el => { el.classList.add('test');});
 .test { background: green; }
 <div> <div> Sibling 0 </div> <div> Parent <div data-automationid='pictureupload_1'> pictureupload_1 </div> </div> <input type='text'> <div type='text'> Sibling 2 </div> <input type='test'> <input type='checkbox'> </div>

您可以嘗試使用我的代碼獲取索引元素

const getIndex = (node, groupNode) => {
    return [...groupNode].indexOf(node);
}

Element.prototype.nextAll = function(){
    var allChildren = this.parentNode.children;
    var index = getIndex(this, allChildren);
    allChildren = [...allChildren].filter((item) => {
        return getIndex(item, allChildren) > index;
    });
    return allChildren;
}

正常的jQuery選擇器函數和parent方法應該是清楚的:

document.querySelector("[data-automationid=pictureupload_1]").parentNode

nextAll目前沒有一個原生的 JavaScript 等價物,但我們可以用原生 DOM 方法制作一個。 有兩種方法可以接近它:

  1. 首先選擇所有子元素,然后在某個元素之后過濾所有匹配的兄弟元素,或者
  2. 使用循環。

1.先選擇所有子元素,然后過濾某個元素后所有匹配的兄弟元素

使用.parentNode.children可以部分實現獲取兄弟.parentNode.children 但是不要擔心選擇父元素本身,因為按 DOM 順序過濾很容易。 這使用Node.prototype.compareDocumentPositionElement.prototype.matches 我還包含了一些可選的鏈接,這樣如果parentReference === documentparentReference.parentNode.children不會拋出錯誤。 那么它默認為一個空數組。

const selectParentMatchingNextSiblings = (jQuerySelector, siblingSelector) => {
    const parentReference = document.querySelector(jQuerySelector).parentNode;
    
    return Array.from(parentReference.parentNode?.children ?? [])
      .filter((element) => parentReference.compareDocumentPosition(element) & Document.DOCUMENT_POSITION_FOLLOWING && element.matches(siblingSelector));
  };

selectParentMatchingNextSiblings("[data-automationid=pictureupload_1]", "input[type=text]");

范圍的替代方法

Range API還可用於文檔順序比較。

const selectParentMatchingNextSiblings = (jQuerySelector, siblingSelector) => {
    const parentReference = document.querySelector(jQuerySelector).parentNode,
      nextSiblings = document.createRange();
    
    nextSiblings.setStartAfter(parentReference);
    nextSiblings.setEndAfter(parentReference.parentNode?.lastElementChild ?? parentReference);
    
    return Array.from(parentReference.parentNode?.children ?? [])
      .filter((element) => nextSiblings.comparePoint(element, 0) === 0 && element.matches(siblingSelector));
  };

selectParentMatchingNextSiblings("[data-automationid=pictureupload_1]", "input[type=text]");

請注意,此選項不適用於"html"作為第一個選擇器。

2. 使用循環

const selectMatchingNextSiblings = (jQuerySelector, siblingSelector) => {
    const parentReference = document.querySelector(jQuerySelector).parentNode,
      result = [];
    let currentElement = parentReference.nextElementSibling;
    
    while(currentElement){
      if(currentElement.matches(siblingSelector)){
        result.push(currentElement);
      }
      
      currentElement = currentElement.nextElementSibling;
    }
    
    return result;
  };

selectParentMatchingNextSiblings("[data-automationid=pictureupload_1]", "input[type=text]");

這應該是不言自明的。 其他答案中的選項也很好。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM