首页 > 解决方案 > 单击输入字段时,ANTD 下拉菜单不应关闭

问题描述

我正在尝试使用 ANTD 组件实现下拉功能,例如:

  1. 当输入字段中有一些文本时,应显示下拉菜单。
  2. 当我在下拉列表之外单击时,下拉列表应该关闭。
  3. 当我单击下拉菜单时,下拉菜单不应关闭。
  4. 如果输入字段上没有文本,则不应打开下拉菜单。
  5. 如果有一些文本,单击输入字段时下拉菜单不应关闭。

我无法达到第五个要求。每当我单击输入字段时,下拉菜单会打开和关闭,如下所示: 在此处输入图像描述

这不应该发生。

示例工作代码:

state = {
    visible: false,
    searchInput: null
  };

handleVisibleChange = flag => {
    if (!this.isDefined(this.state.searchInput)) {
      this.removeDropdown();
    } else {
      this.setState({ visible: flag });
    }
  };

removeDropdown = () => {
  this.setState({ visible: false });
};

showDropdown = () => {
  this.setState({ visible: true });
};

checkInput = value => {
  if (this.isDefined(value)) {
    this.setState({ searchInput: value });
    this.showDropdown();
  } else {
    this.setState({ searchInput: null });
    this.removeDropdown();
  }
};

render() {
  const menu = (
    <Menu>
      <Menu.Item key="1">Clicking me will not close the menu.</Menu.Item>
      <Menu.Item key="2">Clicking me will not close the menu also.</Menu.Item>
      <Menu.Item key="3">Clicking me will not close the menu.</Menu.Item>
    </Menu>
  );
  return (
    <Dropdown
      overlay={menu}
      trigger={['click']}
      onVisibleChange={this.handleVisibleChange}
      visible={this.state.visible}
    >
      <Search
        value={this.state.searchInput}
        onInput={e => this.checkInput(e.target.value)}
      />
    </Dropdown>
  );
}

完整代码:https ://stackblitz.com/edit/react-srz4ml?file=index.js

我尝试使用onBlur()andonFocus()方法代替,onVisibleChange()但它违反了第三个要求。

有人可以帮我吗?

谢谢。

标签: javascriptreactjsantd

解决方案


我已经对此进行了一些实验,似乎没有一种超级简单的方法可以做到这一点,但我能够使它与一些丑陋的状态管理一起工作。https://stackblitz.com/edit/react-srz4ml-p6faxs?file=index.js 希望你能想出一个更干净的解决方案。

state = {
    searchInput: null,
    isVisable: false,
    clickedPrevState: false
  };

  render() {
    const getNewState = (prevState, event, value) => {
      console.log(prevState, event, value);
      let newState = { ...prevState, clickedPrevState: false };
      switch (event) {
        case 'input':
          newState.isVisable = value ? true : false;
          newState.searchInput = value;
          break;
        case 'clicked':
          if (prevState.searchInput) {
            newState.isVisable = true;
            newState.clickedPrevState = true; // used by next getNewState to determine if it was a click on input
          } else newState.isVisable = false;
          break;
        case 'change':
          if (prevState.searchInput && (value || prevState.clickedPrevState)) {
            newState.isVisable = true;
          } else newState.isVisable = false;
          break;
        default:
          newState.isVisable = false;
      }
      return newState;
    };

    const menu = (
      <Menu>
        <Menu.Item key="1">Clicking me will not close the menu.</Menu.Item>
        <Menu.Item key="2">Clicking me will not close the menu also.</Menu.Item>
        <Menu.Item key="3">Clicking me will not close the menu.</Menu.Item>
      </Menu>
    );
    return (
      <Dropdown
        overlay={menu}
        trigger={['click']}
        visible={this.state.isVisable}
        onVisibleChange={flag =>
          this.setState(prevstate => {
            return getNewState(prevstate, 'change', flag);
          })
        }
        onClick={e =>
          this.setState(prevstate => {
            return getNewState(prevstate, 'clicked');
          })
        }
      >
        <Search
          value={this.state.searchInput}
          onInput={e =>
            this.setState(prevstate => {
              return getNewState(prevstate, 'input', e.target.value);
            })
          }
        />
      </Dropdown>
    );
}

推荐阅读