【问题标题】:ANTD Dropdown should not close when clicked on the Input field单击输入字段时,ANTD 下拉菜单不应关闭
【发布时间】:2021-08-12 06:50:48
【问题描述】:

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

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

我无法达到第 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()onFocus() 方法而不是onVisibleChange(),但它违反了第三个要求。

有人可以帮我解决这个问题吗?

谢谢。

【问题讨论】:

    标签: javascript reactjs antd


    【解决方案1】:

    我已经对此进行了一些实验,似乎没有一种超级简单的方法可以做到这一点,但我能够使其与一些丑陋的状态管理一起工作。 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>
        );
    }
    

    【讨论】:

    • 我在我的项目中尝试了相同的逻辑,但首先触发了onVisibleChange,然后触发了onClick 事件(在给定的代码沙箱中,顺序相反)。因此,当我首先单击搜索框时,change 事件将 clickedPrevState 设置为 false,然后 clicked 事件将状态设置为 true。因此,如果我在clickedPrevState 之外单击,此时仍然为真,并且下拉菜单不会消失。如果我再次单击它会关闭。是否可以更改触发onClickonVisisbleChange 事件的顺序?
    • 有趣的是它会被逆转。可能是不同版本的antd。如果是这样,您将不得不更改逻辑。只看它而不测试它我认为它应该通过使用 clickedPrevState 删除所有逻辑来工作。当我对其进行测试时,这些事件似乎是同一渲染周期的一部分,因此应该可以正常工作而不会导致菜单闪烁。
    猜你喜欢
    • 2021-11-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多