美文网首页
React 外部点击模式

React 外部点击模式

作者: _____西班木有蛀牙 | 来源:发表于2019-06-10 14:17 被阅读0次
    // 用户可以通过点击元素以外的地方来关闭已打开的弹出框。
    
    // 主要原理是在 window 对象中附上一个 click 事件以关闭弹窗:
    
    class OuterClickExample extends React.Component {
    constructor(props) {
        super(props);
    
        this.state = { isOpen: false };
        this.toggleContainer = React.createRef();
    
        this.onClickHandler = this.onClickHandler.bind(this);
        this.onClickOutsideHandler = this.onClickOutsideHandler.bind(this);
      }
    
      componentDidMount() {
        window.addEventListener('click', this.onClickOutsideHandler);
      }
    
      componentWillUnmount() {
        window.removeEventListener('click', this.onClickOutsideHandler);
      }
    
      onClickHandler() {
        this.setState(currentState => ({
          isOpen: !currentState.isOpen
        }));
      }
    
      onClickOutsideHandler(event) {
        if (this.state.isOpen && !this.toggleContainer.current.contains(event.target)) {
          this.setState({ isOpen: false });
        }
      }
    
      render() {
        return (
          <div ref={this.toggleContainer}>
            <button onClick={this.onClickHandler}>Select an option</button>
            {this.state.isOpen ? (
              <ul>
                <li>Option 1</li>
                <li>Option 2</li>
                <li>Option 3</li>
              </ul>
            ) : null}
          </div>
        );
      }
    }
    
    // 使用正确的事件触发器,比如 onBlur 和 onFocus
    
    class BlurExample extends React.Component {
      constructor(props) {
        super(props);
    
        this.state = { isOpen: false };
        this.timeOutId = null;
    
        this.onClickHandler = this.onClickHandler.bind(this);
        this.onBlurHandler = this.onBlurHandler.bind(this);
        this.onFocusHandler = this.onFocusHandler.bind(this);
      }
    
      onClickHandler() {
        this.setState(currentState => ({
          isOpen: !currentState.isOpen
        }));
      }
    
      // 我们在下一个时间点使用 setTimeout 关闭弹窗。
      // 这是必要的,因为失去焦点事件会在新的焦点事件前被触发,
      // 我们需要通过这个步骤确认这个元素的一个子节点
      // 是否得到了焦点。
      onBlurHandler() {
        this.timeOutId = setTimeout(() => {
          this.setState({
            isOpen: false
          });
        });
      }
    
      // 如果一个子节点获得了焦点,不要关闭弹窗。
      onFocusHandler() {
        clearTimeout(this.timeOutId);
      }
    
      render() {
        // React 通过把失去焦点和获得焦点事件传输给父节点
        // 来帮助我们。
        return (
          <div onBlur={this.onBlurHandler}
               onFocus={this.onFocusHandler}>
    
            <button onClick={this.onClickHandler}
                    aria-haspopup="true"
                    aria-expanded={this.state.isOpen}>
              Select an option
            </button>
            {this.state.isOpen ? (
              <ul>
                <li>Option 1</li>
                <li>Option 2</li>
                <li>Option 3</li>
              </ul>
            ) : null}
          </div>
        );
      }
    }
    
    

    相关文章

      网友评论

          本文标题:React 外部点击模式

          本文链接:https://www.haomeiwen.com/subject/mzrzxctx.html