You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MUI DesktopDatePicker在iframe中打开时触发父页面滚动至顶部问题求助

解决iframe中MUI DesktopDatePicker点击触发父页面滚动的问题

问题背景

在iframe内使用MUI DesktopDatePicker组件时,点击打开日期选择器的按钮会导致父页面自动滚动至顶部。尝试通过强制保持按钮聚焦来修复时,又出现了点击组件外部后页面滚动回聚焦元素的新问题。

原实现代码片段:

useEffect(() => {
  if (datePicker.current) {
    const blurPreventButton = datePicker.current.parentElement?.children[1].children[0];
    if (blurPreventButton) {
      blurPreventButton.id = 'openDatePickerButton';
      iframeBlurManipulation();
    }
  }
}, []);

export default function iframeBlurManipulation() {
  const button = document.querySelector('#openDatePickerButton');
  if (button) {
    button.addEventListener('blur', (event) => {
      event.target.focus();
    });
  }
}

可行解决方案

方案1:阻止打开按钮聚焦时的滚动行为

问题核心是按钮聚焦时触发了跨iframe的滚动同步,直接给按钮添加preventScrollOnFocus属性即可解决:

<DesktopDatePicker
  className="capitalize-text"
  value={selectedDate}
  autoFocus={false}
  slots={{
    day: ServerDay,
  }}
  inputRef={datePicker}
  onChange={handleDateChange}
  shouldDisableDate={shouldDisableDate}
  minDate={dayjs(firstValidDate)}
  slotProps={{
    popper: {
      disablePortal: true,
      autoFocus: false,
    },
    // 给打开按钮添加阻止滚动的属性
    openPickerButton: {
      preventScrollOnFocus: true,
    },
  }}
  maxDate={dayjs(Object.values(departureDates).pop() || '')}
/>

添加后,移除之前的iframeBlurManipulation函数和对应的useEffect逻辑即可,无需强制保持按钮聚焦。

方案2:拦截iframe内的滚动事件传播

如果方案1不生效,可以通过监听iframe内部的滚动事件,阻止其冒泡到父页面:

useEffect(() => {
  const stopScrollPropagation = (e) => e.stopPropagation();
  window.addEventListener('scroll', stopScrollPropagation);
  return () => window.removeEventListener('scroll', stopScrollPropagation);
}, []);

方案3:自定义打开按钮逻辑

完全接管打开按钮的点击行为,避免默认聚焦触发的滚动:

const [isPickerOpen, setIsPickerOpen] = useState(false);

const handleOpenPicker = (e) => {
  e.preventDefault(); // 阻止默认聚焦行为
  setIsPickerOpen(true);
};

<DesktopDatePicker
  className="capitalize-text"
  value={selectedDate}
  autoFocus={false}
  open={isPickerOpen}
  onClose={() => setIsPickerOpen(false)}
  slots={{
    day: ServerDay,
    openPickerButton: () => (
      <button onClick={handleOpenPicker} type="button">
        选择日期
      </button>
    ),
  }}
  inputRef={datePicker}
  onChange={handleDateChange}
  shouldDisableDate={shouldDisableDate}
  minDate={dayjs(firstValidDate)}
  slotProps={{
    popper: {
      disablePortal: true,
      autoFocus: false,
    },
  }}
  maxDate={dayjs(Object.values(departureDates).pop() || '')}
/>

以上方案均可解决原问题,同时避免点击外部页面滚动回聚焦元素的副作用。

内容的提问来源于stack exchange,提问作者Rolandas Dovydėnas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 20:58:08