猿问

纯 Javascript 获取父母

我创建了一个基于.parents()的片段,没有 jquery - 或 querySelectorAll 为父母

  function getParents (el, _class) {

    let doc = document

    let parents = []

    let p = el.parentNode


    while (p !== doc) {

      let o = p

      parents.push(o)

      p = o.parentNode

    }

    parents.push(doc)

    return parents[parents.map(x => x.className).indexOf(_class)]

  }


document.querySelectorAll('.child1').forEach((e,i)=>{

  console.log(getParents(e, 'child4'))

})

<div class="parent">

  <div class="child5">

    <div class="child4">

      <div class="child3">

        <div class="child2">

          <div class="child1">

            1

          </div>

        </div>

      </div>

    </div>

  </div>

</div>



  <div class="parent">

  <div class="child5">

    <div class="child4">

      <div class="child3">

        <div class="child2">

          <div class="child1">

            2

          </div>

        </div>

      </div>

    </div>

  </div>

</div>



  <div class="parent">

  <div class="child5">

    <div class="child4 hello">  <!-- problem here -->

      <div class="child3">

        <div class="child2">

          <div class="child1">

            3

          </div>

        </div>

      </div>

    </div>

  </div>

</div>

如果<div class="child4 hello">没有hello我可以获得所有child4,如果hello添加或添加任何其他内容,我将无法获得child4。我使用indexOf()我认为不应该-1或未定义。有人可以纠正我错误在哪里吗?谢谢


繁华开满天机
浏览 182回答 3
3回答

白衣非少年

问题是,当您这样做时,parents.map(x => x.className)您将获得一个包含每个元素的完整类字符串的数组。所以结果看起来像(简化)[ "child4 hello" ],你尝试indexOf("child4")在那个数组上做。由于没有简单的成员"child4",所以失败了。这是说明的有问题的代码:function getParents (el, _class) {&nbsp; &nbsp; let doc = document&nbsp; &nbsp; let parents = []&nbsp; &nbsp; let p = el.parentNode&nbsp; &nbsp; while (p !== doc) {&nbsp; &nbsp; &nbsp; let o = p&nbsp; &nbsp; &nbsp; parents.push(o)&nbsp; &nbsp; &nbsp; p = o.parentNode&nbsp; &nbsp; }&nbsp; &nbsp; parents.push(doc)&nbsp; &nbsp; let mappedClassName = parents.map(x => x.className)&nbsp; &nbsp; console.log("mappedClassName", mappedClassName)&nbsp; &nbsp; let indexOf = mappedClassName.indexOf(_class);&nbsp; &nbsp; console.log("indexOf", indexOf)&nbsp; &nbsp; return parents[indexOf]&nbsp; }document.querySelectorAll('.child1').forEach((e,i)=>{&nbsp; console.log(getParents(e, 'child4'))})<div class="parent">&nbsp; <div class="child5">&nbsp; &nbsp; <div class="child4 hello">&nbsp; <!-- problem here -->&nbsp; &nbsp; &nbsp; <div class="child3">&nbsp; &nbsp; &nbsp; &nbsp; <div class="child2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <div class="child1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 3&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </div>&nbsp; &nbsp; &nbsp; &nbsp; </div>&nbsp; &nbsp; &nbsp; </div>&nbsp; &nbsp; </div>&nbsp; </div></div>此代码适用于字符串:let indexOf = "child4 hello".indexOf("child4");console.log(indexOf);但是,它不一定能正常工作://the class is NOT child4let indexOf = "child42 hello".indexOf("child4");console.log(indexOf);您应该使用Element.classList进行更准确的类检查:let div1 = document.getElementById("one");let div2 = document.getElementById("two");let _class = "child4";console.log(`div1 has ${_class}`, div1.classList.contains(_class))console.log(`div2 has ${_class}`, div2.classList.contains(_class))<div id="one" class="child4 hello"></div><div id="two" class="child42 hello"></div>如果你把它与Array#findIndex实现你想要的结合起来:function getParents (el, _class) {&nbsp; &nbsp; let doc = document&nbsp; &nbsp; let parents = []&nbsp; &nbsp; let p = el.parentNode&nbsp; &nbsp; while (p !== doc) {&nbsp; &nbsp; &nbsp; let o = p&nbsp; &nbsp; &nbsp; parents.push(o)&nbsp; &nbsp; &nbsp; p = o.parentNode&nbsp; &nbsp; }&nbsp; &nbsp; parents.push(doc)&nbsp; &nbsp; return parents[parents.map(x => x.classList).findIndex(cl => cl.contains(_class))]&nbsp; &nbsp; //&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ^^^^^^^^^&nbsp; ^^^^^^^^^&nbsp; }document.querySelectorAll('.child1').forEach((e,i)=>{&nbsp; console.log(getParents(e, 'child4'))})<div class="parent">&nbsp; <div class="child5">&nbsp; &nbsp; <div class="child4">&nbsp; &nbsp; &nbsp; <div class="child3">&nbsp; &nbsp; &nbsp; &nbsp; <div class="child2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <div class="child1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 1&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </div>&nbsp; &nbsp; &nbsp; &nbsp; </div>&nbsp; &nbsp; &nbsp; </div>&nbsp; &nbsp; </div>&nbsp; </div></div>&nbsp; <div class="parent">&nbsp; <div class="child5">&nbsp; &nbsp; <div class="child4">&nbsp; &nbsp; &nbsp; <div class="child3">&nbsp; &nbsp; &nbsp; &nbsp; <div class="child2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <div class="child1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 2&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </div>&nbsp; &nbsp; &nbsp; &nbsp; </div>&nbsp; &nbsp; &nbsp; </div>&nbsp; &nbsp; </div>&nbsp; </div></div>&nbsp; <div class="parent">&nbsp; <div class="child5">&nbsp; &nbsp; <div class="child4 hello">&nbsp; <!-- problem here -->&nbsp; &nbsp; &nbsp; <div class="child3">&nbsp; &nbsp; &nbsp; &nbsp; <div class="child2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <div class="child1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 3&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </div>&nbsp; &nbsp; &nbsp; &nbsp; </div>&nbsp; &nbsp; &nbsp; </div>&nbsp; &nbsp; </div>&nbsp; </div></div>您可以通过删除.map和运行中的逻辑来使代码稍微短一些.findIndex:parents.findIndex(x => x.classList.contains(_class))但是,尽管如此,您的算法只检查classes。您可以使用以下命令轻松扩展它以使用任何选择器Element.matches:function getParents (el, selector) {&nbsp; &nbsp; let doc = document&nbsp; &nbsp; let parents = []&nbsp; &nbsp; let p = el.parentNode&nbsp; &nbsp; while (p !== doc) {&nbsp; &nbsp; &nbsp; let o = p&nbsp; &nbsp; &nbsp; parents.push(o)&nbsp; &nbsp; &nbsp; p = o.parentNode&nbsp; &nbsp; }&nbsp; &nbsp; parents.push(doc)&nbsp; &nbsp; return parents[parents.findIndex(x => x instanceof Element && x.matches(selector))]&nbsp; &nbsp; // only check Elements -------------> ^^^^^^^^^^^^^^^^^^^^&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&nbsp; }document.querySelectorAll('.child1').forEach((e,i)=>{&nbsp; console.log('.child4', getParents(e, '.child4'))})document.querySelectorAll('.child1').forEach((e,i)=>{&nbsp; console.log('#parentTwo.child4', getParents(e, '#parentTwo.child4'))})<div class="parent">&nbsp; <div class="child5">&nbsp; &nbsp; <div id="parentOne" class="child4">&nbsp; &nbsp; &nbsp; <div class="child3">&nbsp; &nbsp; &nbsp; &nbsp; <div class="child2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <div class="child1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 1&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </div>&nbsp; &nbsp; &nbsp; &nbsp; </div>&nbsp; &nbsp; &nbsp; </div>&nbsp; &nbsp; </div>&nbsp; </div></div>&nbsp; <div class="parent">&nbsp; <div class="child5">&nbsp; &nbsp; <div id="parentTwo" class="child4">&nbsp; &nbsp; &nbsp; <div class="child3">&nbsp; &nbsp; &nbsp; &nbsp; <div class="child2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <div class="child1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 2&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </div>&nbsp; &nbsp; &nbsp; &nbsp; </div>&nbsp; &nbsp; &nbsp; </div>&nbsp; &nbsp; </div>&nbsp; </div></div>&nbsp; <div class="parent">&nbsp; <div class="child5">&nbsp; &nbsp; <div id="parentThree" class="child4 hello">&nbsp; &nbsp; &nbsp; <div class="child3">&nbsp; &nbsp; &nbsp; &nbsp; <div class="child2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <div class="child1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 3&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </div>&nbsp; &nbsp; &nbsp; &nbsp; </div>&nbsp; &nbsp; &nbsp; </div>&nbsp; &nbsp; </div>&nbsp; </div></div>

明月笑刀无情

问题是你得到一个元素列表,你将它们映射到元素' className,当目标元素有更多的child4类时,数组中的值将是child4 hello,当你正在寻找索引时child4数组中的值,child4 hello将不匹配。而不是Array.indexOf您可以使用Array.find.&nbsp; function getParents (el, _class) {&nbsp; &nbsp; let doc = document&nbsp; &nbsp; let parents = []&nbsp; &nbsp; let p = el.parentNode&nbsp; &nbsp; while (p !== doc) {&nbsp; &nbsp; &nbsp; let o = p&nbsp; &nbsp; &nbsp; parents.push(o)&nbsp; &nbsp; &nbsp; p = o.parentNode&nbsp; &nbsp; }&nbsp; &nbsp; parents.push(doc)&nbsp; &nbsp; return parents.find(e => e.className.includes(_class))&nbsp; }document.querySelectorAll('.child1').forEach((e,i)=>{&nbsp; console.log(getParents(e, 'child4'))})<div class="parent">&nbsp; <div class="child5">&nbsp; &nbsp; <div class="child4">&nbsp; &nbsp; &nbsp; <div class="child3">&nbsp; &nbsp; &nbsp; &nbsp; <div class="child2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <div class="child1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 1&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </div>&nbsp; &nbsp; &nbsp; &nbsp; </div>&nbsp; &nbsp; &nbsp; </div>&nbsp; &nbsp; </div>&nbsp; </div></div>&nbsp; <div class="parent">&nbsp; <div class="child5">&nbsp; &nbsp; <div class="child4">&nbsp; &nbsp; &nbsp; <div class="child3">&nbsp; &nbsp; &nbsp; &nbsp; <div class="child2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <div class="child1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 2&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </div>&nbsp; &nbsp; &nbsp; &nbsp; </div>&nbsp; &nbsp; &nbsp; </div>&nbsp; &nbsp; </div>&nbsp; </div></div>&nbsp; <div class="parent">&nbsp; <div class="child5">&nbsp; &nbsp; <div class="child4 hello">&nbsp; <!-- problem here -->&nbsp; &nbsp; &nbsp; <div class="child3">&nbsp; &nbsp; &nbsp; &nbsp; <div class="child2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <div class="child1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 3&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </div>&nbsp; &nbsp; &nbsp; &nbsp; </div>&nbsp; &nbsp; &nbsp; </div>&nbsp; &nbsp; </div>&nbsp; </div></div>getParents您可以使用Element.closest代替函数下面是一个例子:const parents = Array.from(document.querySelectorAll('.child1')).map(e => e.closest('.child4'));console.log(parents);<div class="parent">&nbsp; <div class="child5">&nbsp; &nbsp; <div class="child4">&nbsp; &nbsp; &nbsp; <div class="child3">&nbsp; &nbsp; &nbsp; &nbsp; <div class="child2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <div class="child1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 1&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </div>&nbsp; &nbsp; &nbsp; &nbsp; </div>&nbsp; &nbsp; &nbsp; </div>&nbsp; &nbsp; </div>&nbsp; </div></div><div class="parent">&nbsp; <div class="child5">&nbsp; &nbsp; <div class="child4">&nbsp; &nbsp; &nbsp; <div class="child3">&nbsp; &nbsp; &nbsp; &nbsp; <div class="child2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <div class="child1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 2&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </div>&nbsp; &nbsp; &nbsp; &nbsp; </div>&nbsp; &nbsp; &nbsp; </div>&nbsp; &nbsp; </div>&nbsp; </div></div><div class="parent">&nbsp; <div class="child5">&nbsp; &nbsp; <div class="child4 hello">&nbsp; &nbsp; &nbsp; <!-- problem here -->&nbsp; &nbsp; &nbsp; <div class="child3">&nbsp; &nbsp; &nbsp; &nbsp; <div class="child2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <div class="child1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 3&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </div>&nbsp; &nbsp; &nbsp; &nbsp; </div>&nbsp; &nbsp; &nbsp; </div>&nbsp; &nbsp; </div>&nbsp; </div></div>正如@Khauri 提到的,在第一个示例中,与其使用className属性并使用字符串函数来检查该值是否匹配,不如使用该classList属性,因为它具有contains函数。

哔哔one

您可以findIndex像这样使用Array 原型:&nbsp;return parents[parents.map(x => x.className).findIndex(x => x.indexOf(_class) > -1)]function getParents (el, _class) {&nbsp; &nbsp; let doc = document&nbsp; &nbsp; let parents = []&nbsp; &nbsp; let p = el.parentNode&nbsp; &nbsp; while (p !== doc) {&nbsp; &nbsp; &nbsp; let o = p&nbsp; &nbsp; &nbsp; parents.push(o)&nbsp; &nbsp; &nbsp; p = o.parentNode&nbsp; &nbsp; }&nbsp; &nbsp; parents.push(doc)&nbsp; &nbsp; return parents[parents.map(x => x.className).findIndex(x => x.indexOf(_class) > -1)]&nbsp; }document.querySelectorAll('.child1').forEach((e,i)=>{&nbsp; console.log(getParents(e, 'child4'))})<div class="parent">&nbsp; <div class="child5">&nbsp; &nbsp; <div class="child4">&nbsp; &nbsp; &nbsp; <div class="child3">&nbsp; &nbsp; &nbsp; &nbsp; <div class="child2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <div class="child1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 1&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </div>&nbsp; &nbsp; &nbsp; &nbsp; </div>&nbsp; &nbsp; &nbsp; </div>&nbsp; &nbsp; </div>&nbsp; </div></div>&nbsp; <div class="parent">&nbsp; <div class="child5">&nbsp; &nbsp; <div class="child4">&nbsp; &nbsp; &nbsp; <div class="child3">&nbsp; &nbsp; &nbsp; &nbsp; <div class="child2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <div class="child1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 2&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </div>&nbsp; &nbsp; &nbsp; &nbsp; </div>&nbsp; &nbsp; &nbsp; </div>&nbsp; &nbsp; </div>&nbsp; </div></div>&nbsp; <div class="parent">&nbsp; <div class="child5">&nbsp; &nbsp; <div class="child4 hello">&nbsp; <!-- problem here -->&nbsp; &nbsp; &nbsp; <div class="child3">&nbsp; &nbsp; &nbsp; &nbsp; <div class="child2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <div class="child1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 3&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </div>&nbsp; &nbsp; &nbsp; &nbsp; </div>&nbsp; &nbsp; &nbsp; </div>&nbsp; &nbsp; </div>&nbsp; </div></div>
随时随地看视频慕课网APP

相关分类

JavaScript
我要回答