使用 JavaScript 将路径转换为嵌套的无序列表:

Convert paths into a nested unordered list using JavaScript:

我有一个包含以下路径的列表:

<ul class="list">
    <li class="item">/animal/dog/treats/biscuits</li>
    <li class="item">/animal/dog/treats/cookies</li>
    <li class="item">/clothes/shirts</li>
</ul>

我想使用 JavaScript 将上面列表中的每个路径转换为嵌套的无序列表,如下所示:

<ul>
    <li>animals
        <a href="/animal">Shop</a>
        <ul>
            <li>dogs
                <a href="/animal/dog">Shop</a>
                <ul>
                    <li>treats
                        <a href="/animal/dog/treats">Shop</a>
                        <ul>
                            <li>
                                <a href="/animal/dog/treats/biscuits">biscuits</a>
                            </li>
                            <li>
                                <a href="/animal/dog/treats/cookies">cookies</a>
                            </li>
                        </ul>
                    </li>
                </ul>
            </li>
        </ul>
    </li>
    <li>clothes
        <a href="/clothes">Shop</a>
        <ul>
            <li><a href="/clothes/shirts">shirts</a></li>
        </ul>
    </li>
</ul>

这是预期的输出: output

如果有人可以指导我使用 JavaScript 实现这一目标,我将不胜感激。谢谢!

这里有一些原版 JavaScript 可以完全按照您指定的方式进行操作。我在 'shop' 和列表条目名称之间添加了一个 space 以阻止它们相互生成。希望这对您有所帮助!

let list  = document.querySelector('#list'); // get list
let items = list.querySelectorAll('[class*="item"]'); // get all items in list
let newList = document.createElement('ul');

items.forEach( item => {

  const paths      = item.innerText.split('/');
  paths.splice(0,1); // remove first element since it's empty
  
  let   dir        = newList;
  let   globalPath = "";
  
  for( path of paths ){
  
    globalPath = globalPath + '/' + path;
    
    if( dir[path] == undefined ){
      
      let subList = document.createElement('li'); // begin sublist
        subList.innerText = path + ' '; // add space between the list entry and href
        
        let href = document.createElement('a'); // begin href
          href.href = globalPath;
        subList.appendChild( href ); // end href
        
        if( path != paths[paths.length-1] ){ // prep another ul to go deeper in the list
          href.innerText = "shop";
          let ul = document.createElement('ul');
          subList.appendChild( ul );
          dir[path] = ul;
        }
      dir.appendChild(subList); // end sublist
      
    }
    
    dir = dir[path]; // dive deeper
    
  }
  
} );

list.innerHTML = newList.innerHTML; // replace old list with new list
<ul class="list" id="list">
    <li class="item">/animal/dog/treats/biscuits</li>
    <li class="item">/animal/dog/treats/cookies</li>
    <li class="item">/clothes/shirts</li>
</ul>

星期六 afternoon/evening 无所事事......这就是我整理的。不是第一个答案,而是另一个答案。 ;-)

// convert the menu object into the nested <ul> structure:
function buildShop(pth,mn){
 return Object.entries(mn).sort(([k],[l])=>k.localeCompare(l))
  .map(([sh,o])=>
  '<li>'+
   (Object.entries(o).length
    ? sh+' <a href="'+pth+sh+'">Shop</a><ul>'+ buildShop(pth+sh+'/',o)+'</ul>'
    : '<a href="'+pth+sh+'">'+sh+'</a>')+
  '</li>').join("\n")
}

// Create a "menu" object containing all shops and items:
const menu={};
document.querySelectorAll("ul.list>li").forEach(el=>
 el.textContent.substr(1).split("/")
 .reduce((m,sh)=>m[sh]=m[sh]||{},menu)
);

document.querySelector("ul.list").innerHTML=buildShop('/',menu);
<ul class="list">
<li class="item">/animal/dog/collar</li>
<li class="item">/animal/dog/treats/biscuits</li>
<li class="item">/animal/dog/treats/cookies</li>
<li class="item">/clothes/shirts</li>
<li class="item">/animal/dog/leash</li>
</ul>

我刚刚为每个级别添加了字母排序。这样一开始定义路径的顺序就无关紧要了。