在onChange事件上模糊Material UI Select组件

4

默认情况下,MaterialUI的Select组件在选择选项后仍然保持焦点。在他们的文档中的所有示例中都可以看到这种行为。

我希望在选择了选项后,该元素会失去焦点。以下是我的代码:

const App = () => {
    const [selectedValue, setSelectedValue] = useState('')

    const selectElement = useRef(null);

  return (
        <Select
            native
            ref={selectElement}
            value={selectedValue}
            onChange={(evt) => {
                setSelectedValue(evt.target.value)

                // Attempt at blurring the element upon selection using the useRef:
                selectElement.current.blur(); // Nothing happens

                // Attempt at blurring the element upon selection using activeElement:
                document.activeElement.blur(); // Get Error: "Property 'blur' does not exist on type 'Element'."
            }}
        >
            <option value='option 1'>Option 1</option>
            <option value='option 2'>Option 2</option>
            <option value='option 3'>Option 3</option>
        </Select>
  );
};

如您所见,我尝试使用两种不同的方法来实现这一目标:

  • 通过 useRef():此方法无效,没有任何错误出现,但是不能使我的元素模糊。

  • 通过 document.activeElement:这会导致错误,显然元素上不存在属性 blur

正确的方法是什么,在选择选项后将我的 Select 组件设置为模糊状态?


你需要延迟模糊效果。在选择后,焦点元素不在屏幕上。 - Akxe
1
看起来你正在尝试模糊选项,但我认为你想要模糊选择本身。尝试使用 selectElement.blur(); 或者 evt.target.blur(); - 2pha
请注意,ref 被转发到根元素(一个包装 div),而不是 select,这就是为什么该解决方案无效的原因。 - ericgio
你看到的错误似乎与TypeScript有关,但是你在问题/代码中没有包含任何类型。 - ericgio
我很好奇你为什么想要模糊选择内容。从辅助功能的角度来看,这似乎是一件可怕的事情。 - Ryan Cogswell
我已经在onChange事件中添加了以下内容:setTimeout(() => { document.activeElement.blur() }) 它正在工作。 - Vivek Kapoor
2个回答

4

受@ericgio和@Ryan Cogswell答案的启发,我们可以采用另一种方法解决这个问题。对于非本地元素,我们可以将setTimeout函数分配给onClose,在从菜单中选择选项后模糊该元素。

const App = () => {
  const [selectedValue, setSelectedValue] = useState('');
  const [age, setAge] = React.useState('');

  const handleChange = (event) => {
    setAge(event.target.value);
  };

  return (
    <div>
      <div>
        <Select
          style={{ width: '200px' }}
          native
          value={selectedValue}
          onChange={(evt) => {
            setSelectedValue(evt.target.value);
            evt.target.blur();
          }}>
          <option value="option 1">Option 1</option>
          <option value="option 2">Option 2</option>
          <option value="option 3">Option 3</option>
        </Select>
      </div>
      <FormControl style={{ width: '200px' }}>
        <InputLabel id="demo-simple-select-label">Age</InputLabel>
        <Select
          onClose={() => {
            setTimeout(() => {
              document.activeElement.blur();
            }, 0);
          }}
          value={age}
          onChange={handleChange}>
          <MenuItem value={10}>Ten</MenuItem>
          <MenuItem value={20}>Twenty</MenuItem>
          <MenuItem value={30}>Thirty</MenuItem>
        </Select>
      </FormControl>
    </div>
  );
};

沙盒模式:- https://codesandbox.io/s/wonderful-microservice-xufqc


3

对一些评论进行总结:

如@2pha所建议的,使用evt.target.blur()可能是正确的方式:

const App = () => {
  const [selectedValue, setSelectedValue] = useState('');

  return (
    <Select
      native
      value={selectedValue}
      onChange={(evt) => {
        setSelectedValue(evt.target.value);

        console.log(document.activeElement); // <select>
        evt.target.blur();
        console.log(document.activeElement); // <body>
      }}>
      <option value="option 1">Option 1</option>
      <option value="option 2">Option 2</option>
      <option value="option 3">Option 3</option>
    </Select>
  );
};

沙盒:https://codesandbox.io/s/empty-night-oqlgr

因为它被转发到根元素(一个 div),而不是 select 元素,所以引用无法工作。

你看到的与 document.activeElement 相关的错误似乎与 TypeScript 有关。这是因为 document.activeElement 的泛型类型为 Element,它没有 blur 方法。你需要指定 HTMLSelectElement 类型,但似乎没必要走这条路,因为使用 evt.target 更加直观。


谢谢!这对于原生的Select组件有效,但我也需要用于非原生的组件,但是它们没有blur函数(evt.target只有namevalue属性)。在这种情况下,我该怎么做? - theJuls
我已经fork了你的沙盒示例,以添加非本地选择组件:https://codesandbox.io/s/practical-archimedes-3qcnt - theJuls
2
@theJuls 非本地选择的难点在于时间控制。onChange 是通过单击 MenuItem 触发的,在 onChange 时,MenuItem 仍然具有焦点。在菜单/选择关闭后,选择的 div 接收焦点。如果您在 setTimeout 回调中调用 document.activeElement.blur(),它将按预期工作:https://codesandbox.io/s/non-native-select-blur-jjiu8。 - Ryan Cogswell

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接