为了账号安全,请及时绑定邮箱和手机立即绑定

纯 Javascript 获取父母

纯 Javascript 获取父母

繁华开满天机 2021-06-28 08:55:42
我创建了一个基于.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或未定义。有人可以纠正我错误在哪里吗?谢谢
查看完整描述

3 回答

?
白衣非少年

TA贡献1155条经验 获得超0个赞

问题是,当您这样做时,parents.map(x => x.className)您将获得一个包含每个元素的完整类字符串的数组。所以结果看起来像(简化)[ "child4 hello" ],你尝试indexOf("child4")在那个数组上做。由于没有简单的成员"child4",所以失败了。

这是说明的有问题的代码:

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)

    let mappedClassName = parents.map(x => x.className)

    console.log("mappedClassName", mappedClassName)

    let indexOf = mappedClassName.indexOf(_class);

    console.log("indexOf", indexOf)

    return parents[indexOf]

  }


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

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

})

<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>

此代码适用于字符串:


let indexOf = "child4 hello".indexOf("child4");

console.log(indexOf);

但是,它不一定能正常工作:


//the class is NOT child4

let 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) {

    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.classList).findIndex(cl => cl.contains(_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>

您可以通过删除.map和运行中的逻辑来使代码稍微短一些.findIndex:


parents.findIndex(x => x.classList.contains(_class))

但是,尽管如此,您的算法只检查classes。您可以使用以下命令轻松扩展它以使用任何选择器Element.matches:


function getParents (el, selector) {

    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.findIndex(x => x instanceof Element && x.matches(selector))]

    // only check Elements -------------> ^^^^^^^^^^^^^^^^^^^^              

  }


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

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

})



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

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

})

<div class="parent">

  <div class="child5">

    <div id="parentOne" 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 id="parentTwo" 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 id="parentThree" class="child4 hello">

      <div class="child3">

        <div class="child2">

          <div class="child1">

            3

          </div>

        </div>

      </div>

    </div>

  </div>

</div>


查看完整回答
反对 回复 2021-07-01
?
明月笑刀无情

TA贡献1828条经验 获得超4个赞

问题是你得到一个元素列表,你将它们映射到元素' className,当目标元素有更多的child4类时,数组中的值将是child4 hello,当你正在寻找索引时child4数组中的值,child4 hello将不匹配。而不是Array.indexOf您可以使用Array.find.


  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.find(e => e.className.includes(_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>

getParents您可以使用Element.closest代替函数


下面是一个例子:


const parents = Array.from(document.querySelectorAll('.child1')).map(e => e.closest('.child4'));

console.log(parents);

<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>

正如@Khauri 提到的,在第一个示例中,与其使用className属性并使用字符串函数来检查该值是否匹配,不如使用该classList属性,因为它具有contains函数。


查看完整回答
反对 回复 2021-07-01
?
哔哔one

TA贡献1854条经验 获得超8个赞

您可以findIndex像这样使用Array 原型: return parents[parents.map(x => x.className).findIndex(x => x.indexOf(_class) > -1)]

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).findIndex(x => x.indexOf(_class) > -1)]

  }


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>


查看完整回答
反对 回复 2021-07-01
  • 3 回答
  • 0 关注
  • 181 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信