代码之家  ›  专栏  ›  技术社区  ›  Krishang Sharma

检查主标题时,如何检查所有子项目,反之亦然?

  •  0
  • Krishang Sharma  · 技术社区  · 3 年前

    我正在制作一个下拉列表,如果选中了主标题,我想在其中选择所有子项目;如果选中了所有子项目,我想选择标题。

    const DropDownList = ({ data }) => {
      const [open, setOpen] = useState({});
      const [checked, setChecked] = useState({});
    
      const handleClick = (department) => {
        setOpen((prevOpen) => ({
          ...prevOpen,
          [department]: !prevOpen[department],
        }));
      };
    
      const handleCheck = (item) => {
        setChecked((prevChecked) => ({
          ...prevChecked,
          [item]: !prevChecked[item],
        }));
      };
    
      return (
        <List>
          {data.map((department) => (
            <React.Fragment key={department.department}>
              <ListItem
                sx={{ cursor: "pointer" }}
                onClick={() => handleClick(department.department)}
              >
                <Checkbox
                  checked={checked[department.department] || false}
                  onChange={() => handleCheck(department.department)}
                />
                <ListItemText primary={department.department} />
                {open[department.department] ? <ExpandLess /> : <ExpandMore />}
              </ListItem>
              <Collapse in={open[department.department]} unmountOnExit>
                <List
                  component="div"
                  sx={{ padding: "0 35px", cursor: "pointer" }}
                  disablePadding
                >
                  {department.sub_departments.map((subDepartment) => (
                    <ListItem key={subDepartment}>
                      <Checkbox
                        checked={checked[subDepartment] || false}
                        onChange={() => handleCheck(subDepartment)}
                      />
                      <ListItemText primary={subDepartment} />
                    </ListItem>
                  ))}
                </List>
              </Collapse>
            </React.Fragment>
          ))}
        </List>
      );
    };
    
    export default DropDownList;
    

    这是我的列表组件。

    我知道逻辑,但我不能实现它。我不知道如何实现。我知道通过检查是否所有子项都被检查,我们也可以检查头部,但我不知道该如何实现这一点。

    0 回复  |  直到 3 年前
        1
  •  0
  •   Wongjn    3 年前

    对于“如果选中了主标题,则选择所有子项”,请考虑修改 handleCheck() 通过 item 对象这将使我们知道检查项目的 sub_departments :

    const handleCheck = (item) => {
      setChecked((prevChecked) => ({
        ...prevChecked,
        [item.department]: !prevChecked[item.department],
      }));
    };
    …
    <Checkbox
      …
      onChange={() => handleCheck(department)}
    />
    …
    <Checkbox
      …
      onChange={() => handleCheck({ department: subDepartment })}
    />
    

    如果正在检查,请检查 子部门 :

    const handleCheck = (item, parent = {}) => {
      setChecked((prevChecked) => {
        const list = {
          ...prevChecked,
          [item.department]: !prevChecked[item.department],
        };
    
        if (list[item.department]) {
          if (item.sub_departments) {
            item.sub_departments.forEach(sub => {
              list[sub] = true;
            });
          }
        }
    
        return list;
      });
    };
    

    对于“如果选中了所有子项,则选择标题”,将父部门项作为第二个参数传递给 手柄检查() :

    const handleCheck = (item, parent = {}) => {
      …
    }
    …
    <Checkbox
      …
      onChange={() => handleCheck({ department: subDepartment }, department)}
    />
    

    然后检查上级部门是否所有 子部门 检查:

    const handleCheck = (item, parent = {}) => {
      setChecked((prevChecked) => {
        const list = {
          ...prevChecked,
          [item.department]: !prevChecked[item.department],
        };
    
        if (list[item.department]) {
          …
          if (parent.sub_departments && parent.sub_departments.length) {
            let checkParent = true;
    
            for (const subItem of parent.sub_departments) {
              if (!list[subItem]) {
                checkParent = false;
                break;
              }
            }
    
            if (checkParent) {
              list[parent.department] = true;
            }
          }
        }
    
        return list;
      });
    };
    

    完整示例:

    const { useState } = React;
    const { List, ListItem, Checkbox, ListItemText, Collapse } = MaterialUI;
    
    const ExpandMore = () => 'ExpandMore';
    const ExpandLess = () => 'ExpandLess';
    
    const DropDownList = ({ data }) => {
      const [open, setOpen] = useState({});
      const [checked, setChecked] = useState({});
    
      const handleClick = (department) => {
        setOpen((prevOpen) => ({
          ...prevOpen,
          [department]: !prevOpen[department],
        }));
      };
    
      const handleCheck = (item, parent = {}) => {
        setChecked((prevChecked) => {
          const list = {
            ...prevChecked,
            [item.department]: !prevChecked[item.department],
          };
          
          if (list[item.department]) {
            if (item.sub_departments) {
              item.sub_departments.forEach(sub => {
                list[sub] = true;
              });
            }
     
            if (parent.sub_departments && parent.sub_departments.length) {
              let checkParent = true;
    
              for (const subItem of parent.sub_departments) {
                if (!list[subItem]) {
                  checkParent = false;
                  break;
                }
              }
              
              if (checkParent) {
                list[parent.department] = true;
              }
            }
          }
          
          return list;
        });
      };
    
      return (
        <List>
          {data.map((department) => (
            <React.Fragment key={department.department}>
              <ListItem
                sx={{ cursor: "pointer" }}
                onClick={() => handleClick(department.department)}
              >
                <Checkbox
                  checked={checked[department.department] || false}
                  onChange={() => handleCheck(department)}
                />
                <ListItemText primary={department.department} />
                {open[department.department] ? <ExpandLess /> : <ExpandMore />}
              </ListItem>
              <Collapse in={open[department.department]} unmountOnExit>
                <List
                  component="div"
                  sx={{ padding: "0 35px", cursor: "pointer" }}
                  disablePadding
                >
                  {department.sub_departments.map((subDepartment) => (
                    <ListItem key={subDepartment}>
                      <Checkbox
                        checked={checked[subDepartment] || false}
                        onChange={() => handleCheck({ department: subDepartment }, department)}
                      />
                      <ListItemText primary={subDepartment} />
                    </ListItem>
                  ))}
                </List>
              </Collapse>
            </React.Fragment>
          ))}
        </List>
      );
    };
    
    
    ReactDOM.createRoot(document.getElementById('app')).render(
      <DropDownList
        data={[
          {
            department: 'Fruit',
            sub_departments: ['apple', 'pear', 'orange'],
          },
          {
            department: 'Colors',
            sub_departments: ['Red', 'Green', 'Blue'],
          },
        ]}
      />
    );
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.production.min.js" integrity="sha512-8Q6Y9XnTbOE+JNvjBQwJ2H8S+UV4uA6hiRykhdtIyDYZ2TprdNmWOUaKdGzOhyr4dCyk287OejbPvwl7lrfqrQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.production.min.js" integrity="sha512-MOCpqoRoisCTwJ8vQQiciZv0qcpROCidek3GTFS6KTk2+y7munJIlKCVkFCYY+p3ErYFXCjmFjnfTTRSC1OHWQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
    <script src="https://unpkg.com/@mui/[email protected]/umd/material-ui.development.js"></script>
    
    <div id="app"></div>