Получить строку строки из ul li, используя JavaScript для каждого уровня иерархии

Я делаю этот метод для глубокого присваивания с помощью es6.

function isObject(item) {
  return (item && typeof item === 'object' && !Array.isArray(item) && item !== null)
}

function deepAssign(...objs) {
    if (objs.length < 2) {
        throw new Error('Need two or more objects to merge')
    }

    const target = objs[0]
    for (let i = 1; i < objs.length; i++) {
        const source = objs[i]
        Object.keys(source).forEach(prop => {
            const value = source[prop]
            if (isObject(value)) {
                if (target.hasOwnProperty(prop) && isObject(target[prop])) {
                    target[prop] = deepAssign(target[prop], value)
                } else {
                    target[prop] = value
                }
            } else if (Array.isArray(value)) {
                if (target.hasOwnProperty(prop) && Array.isArray(target[prop])) {
                    const targetArray = target[prop]
                    value.forEach((sourceItem, itemIndex) => {
                        if (itemIndex < targetArray.length) {
                            const targetItem = targetArray[itemIndex]

                            if (Object.is(targetItem, sourceItem)) {
                                return
                            }

                            if (isObject(targetItem) && isObject(sourceItem)) {
                                targetArray[itemIndex] = deepAssign(targetItem, sourceItem)
                            } else if (Array.isArray(targetItem) && Array.isArray(sourceItem)) {
                                targetArray[itemIndex] = deepAssign(targetItem, sourceItem)
                            } else {
                                targetArray[itemIndex] = sourceItem
                            }
                        } else {
                            targetArray.push(sourceItem)
                        }
                    })
                } else {
                    target[prop] = value
                }
            } else {
                target[prop] = value
            }
        })
    }

    return target
}
2
задан marc_s 29 March 2019 в 21:44
поделиться

4 ответа

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

Редактировать:

На основании ваших комментариев параметр по умолчанию (и, вероятно, оператор остальных (...)) вызовет проблемы с вашим браузером.

Разветвленный JSFiddle: https://jsfiddle.net/h56zeqkg/

Вот версия с некоторым унаследованным, дружественным к IE11 JS:

function stringBuilder(ul, prefix) {
    prefix = prefix || '';
    var arr = [].slice.call(ul.children);
    var stringArr = arr.map(function (li) {
        if (li.children.length > 1) {
            return stringBuilder(li.querySelector('ul'), prefix + li.querySelector('a').textContent + '/');
        } else {
            return prefix + li.querySelector('a').textContent;
        }
    });
    return [].concat.apply([], stringArr);
}

stringBuilder(document.querySelector('ul'));
[1113 ] Оригинал:

JSFiddle: https://jsfiddle.net/hvojpds6/

Вот фрагмент кода JS:

function stringBuilder(ul, prefix = '') {
    return [].concat(...Array.from(ul.children).map(li => {
        // recurse
        if (li.children.length > 1) {
            return stringBuilder(li.querySelector('ul'), prefix + li.querySelector('a').textContent + '/');
        } else {
            return prefix + li.querySelector('a').textContent;
        }
    }))
}

stringBuilder(document.querySelector('ul'));

Выходные данные из stringBuilder будет array, со следующим:

stringBuilder(document.querySelector('ul'))
    (7) ["First", "Second/Second - 1", "Second/Second - 2", "Second/Second - 3/Aaa", "Second/Second - 3/Bbb", "Second/Second - 3/Ccc", "Third"]
    0: "First"
    1: "Second/Second - 1"
    2: "Second/Second - 2"
    3: "Second/Second - 3/Aaa"
    4: "Second/Second - 3/Bbb"
    5: "Second/Second - 3/Ccc"
    6: "Third"
    length: 7
    __proto__: Array(0)

0
ответ дан Jack 29 March 2019 в 21:44
поделиться

Пройдите через DOM с помощью рекурсивной функции

//Main recursion
function getChildPaths($elements, parentPath) {

    //Traverse the children of each level
    $elements.children().each(function(){
    
    
      if ($(this).prop('tagName') === 'LI'){       

        //Check if this level has children
        if ($(this).children('UL').length > 0) {

          getChildPaths($(this).children('UL'), `${parentPath}/${$(this).children('A').html()}`) 
          
        }
        else {
          //Show the path if no children
          console.log(`${parentPath}/${$(this).children('A').html()}`)
        }
      }
        
    })   
}


getChildPaths($('#1'), '');
.as-console-wrapper {
  max-height: 200% !important;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul id="1">
    <li><a href="#">First</a></li>
    <li><a href="#">Second</a>
    <ul id="2">
        <li><a href="#">Second - 1</a></li>
        <li><a href="#">Second - 2</a></li>
        <li><a href="#">Second - 3</a>
        <ul id="3">
            <li><a href="#">Aaa</a></li>
            <li><a href="#">Bbb</a></li>
            <li><a href="#">Ccc</a></li>
        </ul>
        </li>
    </ul>
    </li>
    <li><a href="#">Third</a></li>
</ul>

0
ответ дан Charlie H 29 March 2019 в 21:44
поделиться

Рекурсивная функция с использованием методов children() и each()

function getHierarchy($ul, level = '') {

  $ul.children('li').each(function(i, li) {
    let text = $(li).children('a').text();
    let list = $(li).children('ul');
    (list.length) 
      ? getHierarchy(list, level + text + '/')
      : console.log(level + text)
  });
  
}

getHierarchy($('#1'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<ul id="1">
  <li><a href="#">First</a></li>
  <li><a href="#">Second</a>
    <ul id="2">
      <li><a href="#">Second - 1</a></li>
      <li><a href="#">Second - 2</a></li>
      <li><a href="#">Second - 3</a>
        <ul id="3">
          <li><a href="#">Aaa</a></li>
          <li><a href="#">Bbb</a></li>
          <li><a href="#">Ccc</a></li>
        </ul>
      </li>
    </ul>
  </li>
  <li><a href="#">Third</a></li>
</ul>

0
ответ дан Aswin Kumar 29 March 2019 в 21:44
поделиться
function recursive_loop(parent, text) {
    if (text) {
        var c = parent.children;
        for (let i = 0; i < c.length; i++) {
            var t = c[i].getElementsByTagName('a')[0].textContent;                
            if (c[i].getElementsByTagName('ul').length) {
                return recursive_loop(c[i].getElementsByTagName('ul')[0], text + '/' + t);
            }else{
                console.log(text + '/' + t);
            }
        }
    }
}
var parent = document.getElementById('1');
var c = parent.children;
for (let i = 0; i < c.length; i++) {
    var text = c[i].getElementsByTagName('a')[0].textContent;        
    if (c[i].getElementsByTagName('ul').length) {
        recursive_loop(c[i].getElementsByTagName('ul')[0], text);
    }else{
       console.log(text); 
    }
}    
recursive_loop(parent);
0
ответ дан Shoyeb Sheikh 29 March 2019 в 21:44
поделиться
Другие вопросы по тегам:

Похожие вопросы: