javascript - 在 iOS <12 上无法以编程方式触发输入点击
问题描述
我在触发在旧 iOS 设备上打开文件对话框时遇到问题,具体来说,问题似乎出在仍在运行 iOS 12 的设备上。
我正在使用 React-Dropzone 包为文件创建一个放置区,但还添加了一种方法来标记该区域以打开文件对话框以选择文件。
然后我使用 Hammerjs 来检测 onTab 事件。
我可以通过添加一个在onTab
被调用时触发的警报来确定onTab
事件正在触发,并且它是旨在打开对话框的函数,而不是触发文件对话框在较旧的 iOS 设备上打开。
const FileUploadDropzone = () => {
...
const {getRootProps, getInputProps, open, inputRef} = useDropzone({
// Disable click and keydown behavior
noClick: true,
noKeyboard: true,
});
const handleTap = useCallback(() => {
// specific function created by React-Dropzone to open the dialog
open();
// also tried to trigger the input click directly using a ref (have confirmted that the input is correctly referenced)
inputRef.current.click();
}, [allowInteract, uploading, open]);
return (
<Hammer onTap={handleTap}>
<div {...getRootProps()}>
<input {...getInputProps()}/>
{children}
</div>
</Hammer>
);
};
根据我的阅读,输入不能将样式设置为display:none
,如果是,则无法以编程方式触发打开文件对话框。
所以我设置了如下样式:
input {
visibility: hidden;
height: 0px;
width: 0px;
}
我还尝试做的是将输入和传递给组件的子元素包装在标签中,希望能够更好地支持单击标签打开对话框,但即使这样也行不通。
所以现在我很茫然,我不明白如何让它在这些旧的 iOS < 12 设备上工作。
解决方案
该问题似乎与以下事实有关:当自定义单击事件与以编程方式调用输入单击事件之间存在任何延迟时,iOS 12 上的 Safari 不喜欢它。由于在我的例子中输入被深深地嵌套在 DOM 中,当事件的冒泡需要很长时间时会导致问题。
为了解决这个问题,我不得不创建一个 hack,将文件输入附加到 DOM 中,使其尽可能地像<body>
.
我按照这篇文章利用 React.createPortal 将输入附加到组件之外。https://www.jayfreestone.com/writing/react-portals-with-hooks
<div>
我创建了一个函数来在 React 应用程序的顶部底部创建一个空 div 。
function usePortal(cssSelector) {
const rootElemRef = React.useRef(document.createElement('div'));
useEffect(
function setupElement() {
const {current} = rootElemRef;
const parentElem = document.querySelector(cssSelector);
parentElem?.appendChild(current);
return function removeElement() {
current.remove();
};
},
[id]
);
return rootElemRef.current;
}
然后创建了一个组件,该组件将为其子组件附加一个 custom div
,由上面的函数创建
const Modal = ({children}) => {
const target = usePortal('#react-root-div');
return ReactDOM.createPortal(children, target);
};
然后简单地用 Modal 组件包装输入元素,它将(几乎)附加到 DOM 树的底部。
<Modal>
<input {...getInputProps()} />
</Modal>
推荐阅读
- python - 如何在循环中每次将新列提供给 spark 数据框?
- scala - HBaseTableCatalog.tableCatalog 显示错误 - Symbol 'term
类路径中缺少 .yetus.audience'。如何解决这个问题? - php - Typo3 8.7:通过 redirect() 在动作之间传递数据不起作用
- html - Flex Child Height 未拉伸到父级的全高(使用 align-self 拉伸)
- javascript - Can't receive my js and css files with Webpack DevServer
- scala - 在播放框架中创建可写到 HTTP 响应
- amazon-web-services - Amazon s3 测试套件 REST API 签名计算
- angular - Angular 6 refresh Observable 删除后从后端获取所有条目
- javascript - 执行函数时未创建某些 HTML 节点。无法读取 null 的属性“childNodes”,
- opendaylight - Opendaylight REST API 中的配置、操作和操作有什么区别?