Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/392.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何在边栏中创建可折叠列表_Javascript_Css_Reactjs - Fatal编程技术网

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;