仅当事件在具有特定类的dom元素之外时才触发

时间:2018-10-10 18:46:44

标签: javascript jquery reactjs

我有一个事件监听器,可以监听点击。如果这些点击不在给定的dom元素之外,则将调用某个函数(在这种情况下为handleClick)。

现在,仅当事件目标不是具有handleClick引用的事件目标时,才调用函数this.setWrapper

我想知道如果我碰巧也点击了handleClick,如何防止.boxTwo被呼叫。

请注意,我不是要在.boxTwo的div上添加引用,而是要查询DOM以标识在类名为'boxTwo'的div内发生的任何点击,而不是这样做。谢谢!

class App extends React.Component {
  constructor() {
    super();
    this.state = {onClick: false};
    this.setWrapperRef = this.setWrapperRef.bind(this);
    this.handleClick = this.handleClick.bind(this);
  }

  componentDidMount() {
    document.addEventListener('mousedown', this.handleClick);
  }

  componentWillUnmount() {
    document.removeEventListener('mousedown', this.handleClick);
  }

  setWrapperRef(node) {
    this.wrapperRef = node;
  }

  handleClick(event) {
    if (this.wrapperRef && !this.wrapperRef.contains(event.target)) {
      this.setState({onClick: !this.state.onClick});
    }
  }

  render() {
    return (
      <section>
        <div className="boxOne" ref={this.setWrapperRef} />
        <div className="boxTwo" />
        <div>{this.state.onClick ? "On" : "Off"}</div>
      </section>
    );
  }
}

ReactDOM.render(<App />, document.getElementById('app'));
.boxOne {
  height: 100px;
  width: 100px;
  background: pink;
}

.boxTwo {
  margin: 30px;
  height: 50px;
  width: 70px;
  border: solid black 2px;
  background: orange;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<div id="app"></div>

2 个答案:

答案 0 :(得分:1)

  • 您只需要检查event.target.className是否等于boxTwo,就像下面的代码片段一样。
  • 如果目标具有boxOne类,则可以使用相同的“技术”来防止调用函数。
  • 如果要在根本没有className的所有情况下触发,则可以在条件语句!event.target.className
  • 中使用它

多一点点,出于可读性考虑,我会以这种方式完成

handleClick(event) {

    // The ones that don't trigger
    const disabledTriggers = ['boxOne', 'boxTwo'];

    // Ok if no class contained in our event classList are disabled
    const ok = !disabledTriggers.some(c => event.target.classList && event.target.classList.contains(c))
    if(ok) {
      this.setState({onClick: !this.state.onClick});
    }
  }

这是解决方案和最少修改的片段。

class App extends React.Component {
  constructor() {
    super();
    this.state = {onClick: false};
    this.setWrapperRef = this.setWrapperRef.bind(this);
    this.handleClick = this.handleClick.bind(this);
  }

  componentDidMount() {
    document.addEventListener('mousedown', this.handleClick);
  }

  componentWillUnmount() {
    document.removeEventListener('mousedown', this.handleClick);
  }

  setWrapperRef(node) {
    this.wrapperRef = node;
  }

  handleClick(event) {
    
    if (event.target.className !== 'boxTwo' && this.wrapperRef && !this.wrapperRef.contains(event.target)) {
      this.setState({onClick: !this.state.onClick});
    }
  }

  render() {
    return (
      <section>
        <div className="boxOne" ref={this.setWrapperRef} />
        <div className="boxTwo" />
        <div>{this.state.onClick ? "On" : "Off"}</div>
      </section>
    );
  }
}

ReactDOM.render(<App />, document.getElementById('app'));
.boxOne {
  height: 100px;
  width: 100px;
  background: pink;
}

.boxTwo {
  margin: 30px;
  height: 50px;
  width: 70px;
  border: solid black 2px;
  background: orange;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<div id="app"></div>

答案 1 :(得分:0)

让我解释一下我做了什么。

  1. 添加了一种状态来维护其上的元素的类 我们不想拥有onclick。
  2. 在boxOne类中又添加了一个容器类,以检查这是否成立,即使我们有多个类也是如此。
  3. 我检查了event.target.classList(返回当前目标类的列表),并检查是否有来自classList的任何人到状态wrapperRefs。
  4. 如果不存在,则在组件外部单击。我希望这 帮助您。

    如果您有任何疑问,请在下面评论。我想为您提供尽可能多的帮助。

class App extends React.Component {
  constructor() {
    super();
    this.state = {onClick: false, wrapperRefs: ['boxOne', 'boxTwo']};
    this.handleClick = this.handleClick.bind(this);
  }

  componentDidMount() {
    document.addEventListener('mousedown', this.handleClick);
  }

  componentWillUnmount() {
    document.removeEventListener('mousedown', this.handleClick);
  }

  handleClick(event) {
    const classes = event.target.classList;
    const exists = this.state.wrapperRefs.some(ref => classes.contains(ref));
    if(!exists) {
      this.setState({onClick: !this.state.onClick});
    }
  }

  render() {
    return (
      <section>
        <div className="boxOne container" />
        <div className="boxTwo" />
        <div>{this.state.onClick ? "On" : "Off"}</div>
      </section>
    );
  }
}

ReactDOM.render(<App />, document.getElementById('app'));
.boxOne {
  height: 100px;
  width: 100px;
  background: pink;
}

.boxTwo {
  margin: 30px;
  height: 50px;
  width: 70px;
  border: solid black 2px;
  background: orange;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<div id="app"></div>