Как указать целевой элемент c, используя Javascript во вложенном коде? - PullRequest
3 голосов
/ 11 февраля 2020

Я столкнулся с проблемой нацеливания на разные вложенные уровни.

Я прочитал, что можно использовать функцию .children + для l oop, но мне не удалось это сделать.

Допустим, я хочу иметь функцию, где вы проходите уровень вложенности, и он изменит какое-то свойство элемента <li> только на этом уровне.

I wrote this function to add classes to all last <li> 

  function changeElement(){ 
  var lastLi = document.querySelectorAll('li:last-child'); 
    for(i = 0; i < lastLi.length; i++){ 
     lastLi[i].classList.add('last'); 
     lastLi[i].style.background = 'green'; 
    } 
  } 

But now I need to target <li> elements on specific nested level

  function changeElementOnLevel(level) {
  var lastLi = document.querySelectorAll('li:last-child');

  for (i = 0; i < lastLi.length; i++) {
    //if level is 1 than we should change ul.root > li:last-child
    //if level is 3 than we should change ALL <li:last-child> inside ul.root 
> li > ul > 
  }

}
changeElementOnLevel(3)
<ul class='root'>
  <li>Cat
    <ul>
      <li>Eats1</li>
      <li>Sleeps</li>
      <li>Snuggles</li>
      <li>Plays</li>
      <li>Meows</li>
    </ul>
  </li>
  <li>Dog
    <ul>
      <li>Eats2</li>
      <li>Sleeps</li>
      <li>Snuggles</li>
      <li>Plays</li>
      <li>Barks</li>
    </ul>
  </li>
  <li>Fish
    <ul>
      <li>Eats3</li>
      <li>Sleeps</li>
      <li>Swims</li>
      <li>Plays</li>
      <li>Swims</li>
    </ul>
  </li>

Ответы [ 6 ]

1 голос
/ 12 февраля 2020

Вот то, что я придумал на лету:

Во-первых, я бы внес небольшую поправку в ваш HTML (я не уверен, что у вас есть на самом деле ... это может показать, как вам нравится, но конструктивно это вызовет проблемы). Будет трудно установить значение "li", если оно имеет значение И вложенный список. Если вы сбросите innerText или внутренний Html, вы полностью перезапишите остальную часть HTML в этом теге, что означает, что вы потеряете вложенный список. Вы можете обойти это, но зачем беспокоиться, просто закройте эти теги предсказуемо.

(заметьте, я не думаю, что другие ответы решают эту проблему).

Итак, сначала я сделаю это, обратите внимание, как я закрываю "li" для Cat, Dog и Fi sh:

          <ul class='root'>
            <li>Cat</li>
              <ul>
                <li>Eats1</li>
                <li>Sleeps</li>
                <li>Snuggles</li>
                <li>Plays</li>
                <li>Meows</li>
              </ul>
            <li>Dog</li>
              <ul>
                <li>Eats2</li>
                <li>Sleeps</li>
                <li>Snuggles</li>
                <li>Plays</li>
                <li>Barks</li>
              </ul>
              <li>Fish</li>
                <ul>
                  <li>Eats3</li>
                  <li>Sleeps</li>
                  <li>Swims</li>
                  <li>Plays</li>
                  <li>Swims</li>
                </ul>
            </ul>

Теперь вы можете выбирать элементы и устанавливать значения очень просто (а HTML - это звук); Селекторы здесь в основном говорят: «Дайте мне детей li и ul, которые являются ТОЛЬКО прямыми потомками того элемента, с которым я в данный момент работаю» (иначе вы получите их все, независимо от того, насколько глубоко они вложены, чего вы не хотите).

Этот код дает вам желаемый результат, работая рекурсивно над вложенными коллекциями "li" и "ul", обратите внимание, что он также работает с коллекцией верхнего уровня "li":

    const top_layer = document.querySelectorAll ( '.root' );
    const the_new_val = 'THE NEW VAL'; 
    function setProps ( elems, level ) {
      Array.from ( elems ).forEach ( x => { 
        const li = x.querySelectorAll ( ':scope > li' );
        const ul = x.querySelectorAll ( ':scope > ul' );
        if ( Array.from ( li ).length >= level ) {
          li [ level ].innerText = the_new_val;
            setProps ( li [ level ].children, level );
        } 
        if ( Array.from ( ul ).length ) {
            setProps ( ul, level );
        }
      });
    }

setProps ( top_layer, 2 );

Да, вы можете работать с «потомками», но поскольку нас непосредственно интересует установка значений «li», которые всегда появляются в тегах «ul», явные селекторы делают более очевидным, что происходит, и игнорируют любые другие потомки, которые могут будьте рядом, не стесняйтесь вносить эти изменения, если хотите.

Отображаемый результат:

Displayed Result

1 голос
/ 11 февраля 2020

Это зависит от того, что именно вы хотите сделать. Собираетесь ли вы изменить внутренний HTML по клику? Что вы имеете в виду, говоря третий уровень? У вас есть 3 уровня и 3 списка. Требуется больше информации, чтобы помочь вам.

                

  var myElement = document.getElementsByClassName('root');
            var arrayOfPets = myElement[0].children; // we are getting first level, all animals

            var secondLevelArr = [];

            for(i = 0; i < arrayOfPets.length; i++){ 
                arrayOfPets[i].classList.add('last'); 
                arrayOfPets[i].style.background = 'green'; 

                var secondLevel = arrayOfPets[i].children[0].children;
                // Push results to array
                secondLevelArr.push(secondLevel);
               } // will add class and background to all of them
          // To add styles only to last element, you do not need to loop through them

          arrayOfPets[arrayOfPets.length - 1].style.background = 'red'; 

          for(i = 0; i < secondLevelArr.length; i++){

            secondLevelArr[i][0].style.color = "white";

            for(j = 0; j < secondLevelArr[i].length; j++){
                secondLevelArr[i][j].style.textDecoration = 'line-through';
            }

            secondLevelArr[i][secondLevelArr[i].length - 1].style.textDecoration = 'none';
          }
              
 <ul class='root'>
                <li>Cat
                  <ul>
                    <li>Eats1</li>
                    <li>Sleeps</li>
                    <li>Snuggles</li>
                    <li>Plays</li>
                    <li>Meows</li>
                  </ul>
                </li>
                <li>Dog
                  <ul>
                    <li>Eats2</li>
                    <li>Sleeps</li>
                    <li>Snuggles</li>
                    <li>Plays</li>
                    <li>Barks</li>
                  </ul>
                </li>
                <li>Fish
                  <ul>
                    <li>Eats3</li>
                    <li>Sleeps</li>
                    <li>Swims</li>
                    <li>Plays</li>
                    <li>Swims</li>
                  </ul>
                </li>
            </ul>
1 голос
/ 11 февраля 2020

Я считаю, что у вас есть несколько вложенных тегов ul, поэтому в вашем примере ul. root - это уровень 1, а внутренний ul - уровень 2, и если вместо 'Eats1' у вас есть тег ul, он будет уровень 3 и ... Используйте эту функцию:

function changeElementOnLevel(level){
    let query = 'ul.root>li';
    for (let i = 1; i < level; i++) {
        query += '>ul>li'
    }
    query += ':last-child'
    var lastLi = document.querySelectorAll(query);
    for(i = 0; i < lastLi.length; i++){
        // your code 
    }
 }
0 голосов
/ 12 февраля 2020

Этот код решил мою проблему:

var parent = document.querySelector('.root');

function setFirstItemClass(element, level){
    level = +level;
    if(level == 1){
        console.dir(element);
        if(element.children.length > 0){
            element.children[0].style.backgroundColor = 'red';
        }
    } else {
        if(element.children.length > 0){
            level--;
            for(child of element.children){
                setFirstItemClass(child, level);
            }
        }

    }
}

setFirstItemClass(parent, 3);
0 голосов
/ 11 февраля 2020

Попробуйте, как показано ниже,

Я использовал сочетание селекторов запросов и обхода, чтобы достичь этого,

function changeElementOnLevel(level) {
        var rootElement = document.querySelector(".root");

        let targetLi;
        if (level === 1) {
          targetLi = rootElement.children[rootElement.children.length - 1];
          let ul = targetLi.querySelector("ul"); // Since a ul is also there in level 1, I am expecting we need to change only li value not the ul
          targetLi.textContent = "changed Value";
          targetLi.append(ul);
        } else if (level === 3) {
          targetLi = rootElement.querySelector(
            "li:last-child ul li:last-child"
          );
          targetLi.textContent = "changed Value";
        }
      }

      changeElementOnLevel(3);
<ul class="root">
      <li>
        Cat
        <ul>
          <li>Eats1</li>
          <li>Sleeps</li>
          <li>Snuggles</li>
          <li>Plays</li>
          <li>Meows</li>
        </ul>
      </li>
      <li>
        Dog
        <ul>
          <li>Eats2</li>
          <li>Sleeps</li>
          <li>Snuggles</li>
          <li>Plays</li>
          <li>Barks</li>
        </ul>
      </li>
      <li>
        Fish
        <ul>
          <li>Eats3</li>
          <li>Sleeps</li>
          <li>Swims</li>
          <li>Plays</li>
          <li>Swims</li>
        </ul>
      </li>
    </ul>
0 голосов
/ 11 февраля 2020

Не очень понятно, чего вы пытаетесь достичь :) Но вы можете попробовать :nth-child() - CSS селектор псевдокласса, который позволяет вам выбирать элементы на основе их индекса (порядка исходных кодов) внутри их контейнера.

Это просто пример:

function find(n) {
    // returns NodeList
    var liNodeList = document.querySelectorAll('li:nth-child(' + n + ')');
    console.log(li);

    // if you need to do something with those elements, you can iterate
    for (var i = 0; i < liNodeList.length; ++i) {
        var item = liNodeList[i];
        // do what you need with particular item
    }
}

Кроме того, правильный метод - querySelectorAll(...). То, что вы используете querySelectAll не существует.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...