分享
三行代码  ›  专栏  ›  技术社区  ›  Michał Świderski

当输入失去焦点而未注册时,单击移动的按钮

  •  0
  • Michał Świderski  · 技术社区  · 5 天前

    我在用React创建表单时遇到了一个奇怪的问题(不过,React很可能不是特定的)。表单由一个输入、它下面的一个错误提示和一个按钮组成,所有这些都是垂直堆叠的。输入集中在组件装载上,当用户在输入外部单击时,可能会出现错误提示。当输入被聚焦并且用户试图点击按钮时,它会失去焦点,这可能会导致提示出现。提示会向下推动按钮,从而阻止按钮的click事件注册,从而导致糟糕的用户体验。

    有没有办法在输入失去焦点之前强制点击按钮?

    我在这里复制了这种情况: https://jsfiddle.net/tacticalteapot/b40hLv3c/4/

    function App() {
      const ref = React.useRef(null);
      const [showLabel, setShowLabel] = React.useState(false);
      const [clicked, setClicked] = React.useState(false);
     
      React.useEffect(() => {
        ref.current.focus();
      }, []);
      
      return (
      <div>
        <input ref={ref} onBlur={() => setShowLabel(true)} />
        <div>
          {showLabel && <label>a label appeared that moved the button</label>}
        </div>
        <div>
          <button onClick={() => setClicked(true)}>
            CLICK ME
          </button>
        </div>
        {clicked && <h6 style={{color: 'red'}}>CLICKED</h6>}
      </div>)
    }
    
    2 回复  |  直到 5 天前
        1
  •  1
  •   Tony M    5 天前

    这是因为事件的顺序。 onBlur <label> 直接呈现在按钮的“顶部”。您的单击事件从未注册。要测试这一点,请尝试设置标签的高度,甚至将其包装在另一个具有高度的容器中。或者,在按钮上添加填充,这样按钮就不会被 <标签> -它会注册的。

    显然有更好的造型方法。

    function App() {
      const ref = React.useRef(null);
      const [showLabel, setShowLabel] = React.useState(false);
      const [clicked, setClicked] = React.useState(false);
     
      React.useEffect(() => {
        ref.current.focus();
      }, []);
      
      handleClick = () => {
      setClicked(true);
      }
      
      return (
      <div>
        <input ref={ref} onBlur={() => setShowLabel(true)} />
        <div className="test">
          {showLabel && <label>a label appeared that moved the button</label>}
        </div>
        <div>
          <button style={{padding: "30px"}} onClick={() => handleClick()}>
            CLICK ME
          </button>
        </div>
        {clicked && <h6 style={{color: 'red'}}>CLICKED</h6>}
      </div>)
    }
    
    
    ReactDOM.render(<App/>, document.getElementById('app'));
        2
  •  1
  •   Kamil K    5 天前

    Tab 问题在于用户体验本身以及验证消息如何向下推送页面。

    最好稍微更改用户体验,以便在不推动以下任何元素的情况下为验证错误留出空间:

    https://jsfiddle.net/eucj04np/5/

    另外,请记住添加 aria-describedby 指向带有错误验证消息的元素的id。这将有助于辅助技术在元素聚焦后读取错误内容。