Javascript 如何在边栏中创建可折叠列表
我试图在侧边栏中创建可折叠列表。单击后,我将更改“等参线”状态,并根据此状态显示或隐藏子链接。问题是所有子链接同时打开 检查沙箱:Javascript 如何在边栏中创建可折叠列表,javascript,css,reactjs,Javascript,Css,Reactjs,我试图在侧边栏中创建可折叠列表。单击后,我将更改“等参线”状态,并根据此状态显示或隐藏子链接。问题是所有子链接同时打开 检查沙箱: const边栏=({title,children,data,opened,…attrs})=>{ 常量[isOpen,setTriger]=使用状态(false); 常量handleClick=idx=>{ 设置触发器(!isOpen) }; 返回( {data.map((项目,idx)=>{ 返回item.data的类型==“字符串”? {item.name}:
const边栏=({title,children,data,opened,…attrs})=>{
常量[isOpen,setTriger]=使用状态(false);
常量handleClick=idx=>{
设置触发器(!isOpen)
};
返回(
{data.map((项目,idx)=>{
返回item.data的类型==“字符串”?
{item.name}:
handleClick(idx)}>{item.name}
{item.data.map((subs,id)=>{
返回+++{subs.name};
})}
})}
);
};
编辑:
我做了一个新的三明治,添加了一些过渡。现在打开和关闭都很顺利
检查 现在它打开和关闭 您需要做的是保留您单击的
索引
,并且仅在相同的索引
时显示子项
我还添加了一种关闭和打开的方法
下面是用你问题中的代码来做的
const Sidebar = ({ title, children, data, opened, ...attrs }) => {
const [openedIndex , setTriger] = useState(false);
const handleClick = idx => {
// this ternary makes it possible to open and close
setTriger(idx === openedIndex ? -1 : idx)
};
return (
<SidebarUI>
{data.map((item, idx) => {
return typeof item.data === "string" ?
<div key={idx} >{item.name}</div>:
<Fragment key={idx}>
<div onClick={() => handleClick(idx)}>{item.name}</div>
{// here you check if the idx is the same as the opened one}
{// before showing the data of the item}
{idx === openedIndex && item.data.map((subs, ids) => {
return <Test isOpen={true} key={ids}>++++{subs.name}</Test>;
})}
</Fragment>
})}
</SidebarUI>
);
};
const边栏=({title,children,data,opened,…attrs})=>{
const[openedIndex,setTriger]=useState(false);
常量handleClick=idx=>{
//这种三元结构使开关成为可能
设置触发器(idx==openedIndex?-1:idx)
};
返回(
{data.map((项目,idx)=>{
返回item.data的类型==“字符串”?
{item.name}:
handleClick(idx)}>{item.name}
{//这里检查idx是否与打开的idx相同}
{//在显示项的数据之前}
{idx==openedIndex&&item.data.map((subs,id)=>{
返回+++{subs.name};
})}
})}
);
};
您可以在不使用状态的情况下解决此问题。试着换成这个
<Fragment key={idx}>
<div class="sidebar-item" onClick={e => openSidebar(e)}>
{item.name}
</div>
{item.data.map((subs, ids) => {
return (
<div className="sidebar-subitem" key={ids}>
++++{subs.name}
</div>
);
})}
</Fragment>
添加css
.sidebar-subitem {
display: none;
}
.sidebar-item.open + .sidebar-subitem {
display: block;
}
尝试创建具有折叠图元状态的对象,如下所示:
const Sidebar = ({ title, children, data, opened, ...attrs }) => {
const [collapseElements, setCollapse] = useState({});
const handleClick = idx => {
const currentElements = Object.assign({}, collapseElements);
setCollapse({ ...currentElements, [idx]: !collapseElements[idx] });
};
return (
<SidebarUI>
{data.map((item, idx) => {
return typeof item.data === "string" ? (
<div key={idx}>{item.name}</div>
) : (
<Fragment key={idx}>
<div onClick={() => handleClick(idx)}>{item.name}</div>
{item.data.map((subs, ids) => {
return (
<Test isOpen={collapseElements[idx]} key={ids}>
++++{subs.name}
</Test>
);
})}
</Fragment>
);
})}
</SidebarUI>
);
};
export default Sidebar;
const边栏=({title,children,data,opened,…attrs})=>{
const[collapseElements,setCollapse]=useState({});
常量handleClick=idx=>{
const currentElements=Object.assign({},collapseElements);
setCollapse({…currentElements[idx]:!collapseeElements[idx]});
};
返回(
{data.map((项目,idx)=>{
返回item.data的类型==“字符串”(
{item.name}
) : (
handleClick(idx)}>{item.name}
{item.data.map((subs,id)=>{
返回(
++++{subs.name}
);
})}
);
})}
);
};
导出默认边栏;
结帐
如果有帮助,请告诉我。这当然不比@axeljunes好,但也会起作用,因此我保留了一个单独的切换id列表,并基于此进行切换。 此外,这是我第一次使用挂钩,所以裸露我(请随意纠正我)
const边栏=({title,children,data,opened,…attrs})=>{
//常量[isOpen,setTriger]=使用状态(false);
const[list,setList]=useState([]);
常量handleClick=idx=>{
//设置触发器(!isOpen);
如果(!列表包括(idx))
setList([…list,idx]);
否则{
const newList=list.filter(e=>e!==idx);
设置列表(newList);
}
};
返回(
{data.map((项目,idx)=>{
返回item.data的类型==“字符串”(
{item.name}MAIN
) : (
handleClick(idx)}>中的{item.name}
{item.data.map((subs,id)=>{
返回(
++++{subs.name}端
);
})}
);
})}
);
};
导出默认边栏;
Hi@Vencovsky。我看到您的解决方案存在的问题是,以前单击的元素没有保持打开状态。因为这是一个折叠,用户没有点击关闭它们,所以它们应该保持打开状态。@AxelJunes OP没有说他想要什么,但这也很容易改变。我会保留我的答案,你也保留你的方式,那么OP在他想要的东西上有更多的选择。是的,你是对的,问题中没有具体说明@Yerlan Yeszhanov,你能把问题编辑成包含在内吗?谢谢,这很有效。你能解释一下这个字符串吗。现在我没有机会安慰它。但是我很好奇它是做什么的` setCollapse({…currentElements[idx]:!collapseeElements[idx]});}`没问题。基本上,它所做的是获取以前的可折叠元素(…currentElements
)并将单击的元素及其新值(true/false)添加到相应的位置([idx]:!collapseElements[idx]
)。尝试添加console.log({…currentElements[idx]:!collapseElements[idx]})调用setCollapse
以记录状态对象之前的code>
.sidebar-subitem {
display: none;
}
.sidebar-item.open + .sidebar-subitem {
display: block;
}
const Sidebar = ({ title, children, data, opened, ...attrs }) => {
const [collapseElements, setCollapse] = useState({});
const handleClick = idx => {
const currentElements = Object.assign({}, collapseElements);
setCollapse({ ...currentElements, [idx]: !collapseElements[idx] });
};
return (
<SidebarUI>
{data.map((item, idx) => {
return typeof item.data === "string" ? (
<div key={idx}>{item.name}</div>
) : (
<Fragment key={idx}>
<div onClick={() => handleClick(idx)}>{item.name}</div>
{item.data.map((subs, ids) => {
return (
<Test isOpen={collapseElements[idx]} key={ids}>
++++{subs.name}
</Test>
);
})}
</Fragment>
);
})}
</SidebarUI>
);
};
export default Sidebar;
const Sidebar = ({ title, children, data, opened, ...attrs }) => {
//const [isOpen, setTriger] = useState(false);
const [list, setList] = useState([]);
const handleClick = idx => {
//setTriger(!isOpen);
if(!list.includes(idx))
setList([...list,idx]);
else{
const newList = list.filter(e => e!==idx);
setList(newList);
}
};
return (
<SidebarUI>
{data.map((item, idx) => {
return typeof item.data === "string" ? (
<div key={idx}>{item.name}MAIN</div>
) : (
<Fragment key={idx}>
<div onClick={() => handleClick(idx)}>{item.name}IN</div>
{item.data.map((subs, ids) => {
return (
<Test isOpen={list.includes(idx)} key={ids}>
++++{subs.name}SIDE
</Test>
);
})}
</Fragment>
);
})}
</SidebarUI>
);
};
export default Sidebar;