Material-UI Modal内Blockly文本输入框无法编辑及残影问题求助
问题1:text、math_number类型区块输入框无法输入
原因
Material-UI Modal默认开启焦点锁定机制,会拦截所有不在模态框DOM子树内元素的输入事件,而Blockly的文本输入控件是动态挂载到document.body下的,不属于Modal的DOM子树,因此输入内容被拦截无法生效。你已经配置的disableEnforceFocus仅解决了部分焦点问题,还需要补充配置。
解决方案
在Modal组件上新增disableRestoreFocus属性,同时给Modal的直接子元素添加tabIndex={-1}属性,完整的Modal配置如下:
<Modal open={!!blocklyModalOpenRule} onClose={handleCloseBlocklyModal} aria-labelledby="blockly-modal-label" aria-describedby="blockly-modal-description" disableEnforceFocus disableRestoreFocus // 新增:关闭自动恢复焦点逻辑,避免打断Blockly输入 keepMounted={false} // 新增:关闭模态框时自动卸载内部子组件,解决残影问题 > <div tabIndex={-1} // 新增:让模态框容器可接收焦点,避免焦点管理异常 style={{ top: `50%`, left: `50%`, transform: `translate(-50%, -50%)`, height: "90vh", width: "90vw", position: "absolute", background: "white" }} > <BlocklyContainer /> </div> </Modal>
问题2:关闭模态框后残留Blockly画布残影
原因
- Material-UI Modal默认关闭时不会卸载内部子组件,仅做隐藏处理,你给Blockly容器设置的
z-index:1400高于Modal的默认层级,Modal隐藏后Blockly画布仍会显示在页面上层 - Blockly实例在模态框关闭时没有被主动销毁,其注入的SVG元素和相关DOM节点会残留在页面中
BlocklyContainer被React.memo包裹会缓存组件实例,进一步加重DOM残留问题
解决方案
- 按上面的配置给Modal添加
keepMounted={false}属性,关闭时自动卸载内部子组件 - 在
BlocklyComponent中添加生命周期方法,主动销毁Blockly实例,清理残留DOM:
修改Blockly/BlocklyComponent.js,新增componentWillUnmount逻辑:
class BlocklyComponent extends React.Component { blocklyDiv = React.createRef(); toolbox = React.createRef(); workspace; // 原有代码不变 componentWillUnmount() { if (this.workspace) { Blockly.hideChaff(); // 清理弹出的输入框、下拉框等临时元素 this.workspace.dispose(); // 销毁workspace实例,清理注入的SVG元素 this.workspace = null; } } // 原有代码不变 }
- 移除
BlocklyContainer的React.memo包裹,修改BlocklyContainer.js最后一行导出代码:
// 移除React.memo包裹,避免组件缓存导致的DOM残留 export default BlocklyContainer;
以上修改完成后两个问题都可以完全解决。
内容的提问来源于stack exchange,提问作者Marcel Rösler
相关产品推荐
相关产品推荐

