React Redux onBlur 事件未在 Safari 和 Firefox 中触发

IT技术 javascript reactjs firefox redux react-redux
2021-05-18 08:45:46

这似乎在 Chrome 和 Edge 中完美运行。我有一个工具提示,需要在按钮的onClick 上弹出,然后在onBlur 上消失。出于某种原因,onBlur 事件在 Safari 或 Firefox 上根本不会触发。

我已经尝试在 handleBlur 中登录到控制台,但它并没有那么远,就好像 onBlur 在此上下文中不存在一样。

class Tooltip extends Component {
  componentWillUnmount() {
    this.closeActiveTooltip();
  }

  handleKeyPress = (event) => {
    if (event.keyCode === 27) { // Esc key
      this.closeActiveTooltip();
    }
  }

  handleBlur = () => {
    if (this.props.activeTooltip === this.props.name) {
      // setTimeout is for link click
      setTimeout(this.closeActiveTooltip, 100);
    }
  }

  closeActiveTooltip = () => {
    const { activeTooltip, closeTooltip } = this.props;

    if (activeTooltip) {
      closeTooltip(activeTooltip);
    }
  }

  render() {
    const {
      isOpen,
      text,
      link,
      position,
    } = this.props;
    const popupClassName = getClassNameFor(s, 'popup', `${isOpen && 'open'} ${position}`);
    const linkElement = (
      <div className={s.link}>
        <a
          href={link}
          target="_blank"
          rel="noopener noreferrer"
        >
          More info here
        </a>
      </div>
    );

    return (
      <button
        type="button"
        className={s.root}
        onClick={this.props.toggleTooltip}
        onBlur={this.handleBlur}
        onKeyDown={this.handleKeyPress}
      >
        <svg className={s.icon}>
          <use xlinkHref="#more-info" />
        </svg>
        <div className={popupClassName}>
          {text}
          {link && linkElement}
        </div>
      </button>
    );
  }
}
1个回答

我所知道的是,我永远无法<input />使用 React获得一个专注于挂载的元素(很可能是),可能是因为render()s,所以我使用setTimeout(() => input.focus(), 0)使其异步。所以,焦点处理似乎存在问题......

一个简单的解决方法是:

<button
    onClick={this.handleAction}
    onMouseDown={this.handleFocus}
    onMouseUp={this.handleBlur} />

但是当用户将鼠标按钮按钮中释放出来时,您将永远不会触发onMouseUp.

更好的解决方法是模拟点击

class Tooltip extends Component {
    componentDidMount() {
        document.body.addEventListener('click', this.handleClickOut, false);
    }

    componentWillUnmount() {
        document.body.removeEventListener('click', this.handleClickOut, false);
    }

    handleClickOut = event => {
        if(event.target != this.refs.btn) { // Actually more complicated, event.target can be a child of button (icon, span, etc)
            this.handleBlur();
        }
    }

    handleBlur() {}

    render() {
        return (
            <button
                ref='btn'
                type="button"
            >
                {text}
            </button>
        );
    }
}

可能带有包装按钮的组件

<ClickOut onClickOut={this.handleBlur}>
    <button
        onClick={this.handleAction}
        onMouseDown={this.handleFocus} />
</ClickOut>

任何时候你点击你的文档,如果target不是<button />或者它的子节点之一,触发点击伪事件