1. La primera idea: recursiva
Cualquiera de las ideas se requieren para lograr la atención prestada a la página no se pueden generar directamente después al menú anterior, pero todo lo que necesitan para generar nodos DOM y contenido, sólo una representación de una sola vez a la página.
ideas:
De acuerdo con ID asociado PID y si se trata de un menú de la clase padre-hijo
El final es tan prestando datos obtenidos de forma recursiva a la página, por lo que la necesidad de tener un valor de retorno de la función recursiva;
Ampliar las ideas de contracción:
Encontrar el elemento actual, si se expande, contratada directamente;
Si se contrae, el acceso a todas las etiquetas ul bajo el elemento actual, todos los elementos relacionados todos ocultado, a continuación, se muestra el elemento actual
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script src="data.js"></script>
<style>
.view ul ul{
display: none;
}
.show{
display: block !important;
}
</style>
</head>
<body>
<div class="view">
<!-- <ul>
<li>
<p>一级标题</p>
<ul>
<li>
<p>二级标题</p>
<ul>
<li>
...
</li>
</ul>
</li>
</ul>
</li>
</ul> -->
</div>
<script>
{
/*
思路:
根据pid和id进行关联是否是父子级菜单
最终是将所以递归获得的数据渲染到页面,所以递归函数需要有返回值;
展开收缩思路:
找到当前元素,如果是展开的,直接收缩;
如果是收缩的,获取当前元素下的所有ul标签,将所有同级元素全部隐藏,再将当前元素进行显示
*/
let view = document.querySelector(".view");
let getChild = (id) =>{
//筛选pid等于id的情况就表示有子级
return data.filter(item=>item.pid == id);
}
//最终是不断根据pid等于id的情况进行递归,所以需要将这个写成一个函数不断进行递归
// let inner = '';
// data.forEach(item=>{
// inner +=`
// <ul>
// <li>
// <p>${item.title}</p>
// </li>
// </ul>
// `;
// });
//最终要将所以递归到的inner渲染到页面,所以需要有返回值
let createUl = (data)=>{
//不能在循环里面生成ul,否则会生成多个多个ul
let inner = '<ul>';
data.forEach(item=>{
inner +=`
<li>
<p>${item.title}</p>
${
// 如果当前id还能找到对应pid的子级就继续查找
getChild(item.id)&&createUl(getChild(item.id))
}
</li>
`;
});
inner += '</ul>';
return inner;
}
view.innerHTML = createUl(getChild(-1));
//获取到所有的p标签
let allP = document.querySelectorAll("p");
allP.forEach(item=>{
item.onclick = () =>{
let curUl = item.nextElementSibling;
if(curUl){
// 1. 当前是展开状态,点击之后就收缩起来
if(curUl.classList.contains("show")){
curUl.classList.remove("show");
} else {
// 当前是收缩状态,就把所有的同级收缩起来,然后展开当前的
let allUl = curUl.parentNode.parentNode.querySelectorAll("ul");
//所有的同级收起来
allUl.forEach(item=>{
item.classList.remove("show");
});
//展开当前
curUl.classList.add("show");
}
}
};
});
}
</script>
</body>
</html>
2. El segundo enfoque para lograr: Recursive + DOM
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script src="data.js"></script>
<style>
.view ul ul{
display: none;
}
.show{
display: block !important;
}
</style>
</head>
<body>
<div class="view">
<!-- <ul>
<li>
<p>一级标题</p>
<ul>
<li>
<p>二级标题</p>
<ul>
<li>
...
</li>
</ul>
</li>
</ul>
</li>
</ul> -->
</div>
<script>
{
/*
思路:根据pid和id进行关联是否是父子级菜单
最终是将所以递归获得的数据渲染到页面,所以递归函数需要有返回值
不能生成一级菜单就返回,要等所有的ul都生成后再返回
*/
let view = document.querySelector(".view");
let getChild = (id) =>{
//筛选pid等于id的情况就表示有子级
return data.filter(item=>item.pid == id);
}
//最终是不断根据pid等于id的情况进行递归,所以需要将这个写成一个函数不断进行递归
//最终要将所以递归到的inner渲染到页面,所以需要有返回值
let createUl = (data)=>{
let ul = document.createElement("ul");
data.forEach(item=>{
let li = document.createElement("li");
let p = document.createElement("p");
li.appendChild(p);
p.innerHTML = item.title;
//子级菜单每个都加在li上
if(getChild(item.id)){
li.appendChild(createUl(getChild(item.id)));
}
ul.appendChild(li);
});
return ul;
}
view.appendChild(createUl(getChild(-1)));
//获取到所有的p标签
let allP = document.querySelectorAll("p");
allP.forEach(item=>{
item.onclick = () =>{
let curUl = item.nextElementSibling;
if(curUl){
// 1. 当前是展开状态,点击之后就收缩起来
if(curUl.classList.contains("show")){
curUl.classList.remove("show");
} else {
// 2.当前是收缩状态,就把所有的同级收缩起来,然后展开当前的
let allUl = curUl.parentNode.parentNode.querySelectorAll("ul");
//所有的同级收起来
allUl.forEach(item=>{
item.classList.remove("show");
});
//展开当前
curUl.classList.add("show");
}
}
};
});
}
</script>
</body>
</html>