想要避免在单击 header 时执行多项操作

Want to avoid multiple actions on click of a header

我有一个页面,其中有多个可折叠和可展开的项目。每个项目下面都有一个 header 和一组项目。我向 header 添加了 + 图标,这导致展开并显示其下的项目。单击 - 它会崩溃。这个 header 的末尾有一个开关,它是一种拨动开关。因此,每当我单击此切换按钮时,它也会展开和折叠。我想避免这种行为。此切换被提取为单独的组件,但我想在切换时避免 expand/collapse。

有人可以帮忙吗:

我已经添加了与之关联的文件。

我还添加了沙盒link

沙盒:https://codesandbox.io/s/final-parent-child-oh06i

import React, { Component } from "react";
import isEqual from "lodash.isequal";

import ChildSwitch from "./ChildSwitch";
import ParentSwitch from "./ParentSwitch";
import { PARTIAL } from "./constant";

export default class Setting extends Component {
  state = {
    parent: {
      value:
        this.props.children.length > 1
          ? PARTIAL
          : this.props.children[0].isEnabled
    },
    children: this.props.children,
    navBarStatus: false
  };

  componentDidMount() {
    this.setParentSwitchValue();
  }

  changeNavBar = status => {
    this.setState({ navBarStatus: !status });
  };

  shouldComponentUpdate(nextProps, nextState) {
    return !isEqual(this.state, nextState);
  }

  setChildSwitchValue = (id, isEnabled) => {
    let clickedChild;
    this.setState(
      prevState => ({
        ...prevState,
        children: prevState.children.map(child => {
          if (child.id === id) {
            clickedChild = { ...child, isEnabled: isEnabled };
            return clickedChild;
          } else {
            return child;
          }
        })
      }),
      () => this.setParentSwitchValue(clickedChild)
    );
  };

  setParentSwitchValue = clickedChild => {
    const { children } = this.state;
    let parentVal = PARTIAL;

    if (children.every(({ isEnabled }) => isEnabled === true)) {
      parentVal = true;
    }
    if (children.every(({ isEnabled }) => isEnabled === false)) {
      parentVal = false;
    }

    this.setState(
      prevState => ({
        ...prevState,
        parent: {
          value: parentVal
        }
      }),
      () => {
        this.handleChange();
        if (clickedChild) {
          const changed = {
            parent: {
              name: this.props.name,
              value: parentVal
            },
            child: clickedChild
          };
          console.log("This is the changed child", changed);
        }
      }
    );
  };

  setChildrenValue = value => {
    this.setState(
      prevState => ({
        ...prevState,
        parent: {
          value
        },
        children: prevState.children.map(child => ({
          ...child,
          isEnabled: value
        }))
      }),
      () => {
        this.handleChange();
        console.log("Parent Changed", this.state);
      }
    );
  };

  handleChange = () => {
    const { id, onChange } = this.props;
    onChange(id, this.state);
  };

  handleParentClick = parentVal => {
    if (parentVal !== PARTIAL) {
      this.setChildrenValue(parentVal);
    }
  };

  render() {
    const { parent, children } = this.state;
    const { name } = this.props;
    return (
      <div
        className={`an-panel expand-panel ${
          this.state.navBarStatus ? "expand-open" : "expand-close"
        }`}
      >
        <div
          className="an-panel-header"
          onClick={() => this.changeNavBar(this.state.navBarStatus)}
        >
          <div className="title-holder">
            <span className="toggle-icon fa fa-plus-square" />
            <span className="toggle-icon fa fa-minus-square" />
            <h5>{name}</h5>
          </div>
          <div className="action-holder">
            <div className="status-holder">
              <ParentSwitch
                childrenCount={children.length}
                parentSwitch={parent.value}
                onSelect={this.handleParentClick}
              />
            </div>
          </div>
        </div>
        {children.map(({ id, name, isEnabled }) => (
          <div className="an-panel-body" key={id}>
            <ul className="applications-list-holder">
              <li>
                <div className="name">{name}</div>
                <div className="status">
                  <ChildSwitch
                    switchName={id}
                    selected={isEnabled}
                    onSelect={this.setChildSwitchValue}
                  />
                </div>
              </li>
            </ul>
          </div>
        ))}
      </div>
    );
  }
}


您要找的是event.stopPropagation()。这会将 event 隔离到仅触发的执行块(及其子块),同时还会忽略父标记中的任何 events

现在,当您切换 ParentSwitch 时,它会触发父 div 的 onClick 处理程序,停止执行任何父事件(如 expand/collapse)。然后,onSelect 事件执行。

创建一个事件处理程序来像这样触发它:

  stopParentTrigger = e => {
    e.stopPropagation();
  };

然后将其用作包装 ParentSwitch 组件的 div 的 onClick 处理程序。

  <div className="status-holder" onClick={this.stopParentTrigger}>
      <ParentSwitch
        childrenCount={children.length}
        parentSwitch={parent.value}
        onSelect={e => this.handleParentClick(e)}
      />
  </div>

查看工作沙箱:https://codesandbox.io/s/final-parent-child-qm61n