【问题标题】:Input click can't be triggered programanticly on iOS <12在 iOS <12 上无法以编程方式触发输入点击
【发布时间】:2021-01-02 00:18: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

【问题讨论】:

    标签: javascript css ios mobile-safari react-dropzone


    【解决方案1】:

    这个问题似乎与一个问题有关,即 iOS 12 上的 Safari 在自定义点击事件和以编程方式调用输入点击事件之间存在任何延迟时不喜欢它。由于在我的例子中输入是深深嵌套在 DOM 中的,所以当事件的冒泡需要很长时间时会导致问题。

    为了解决这个问题,我不得不创建一个 hack,将文件输入附加到 DOM 中,使其尽可能像 &lt;body&gt; 的孙子。

    我按照这篇文章使用 React.createPortal 将输入附加到组件之外。 https://www.jayfreestone.com/writing/react-portals-with-hooks

    我创建了一个函数来在 React 应用程序的顶部 &lt;div&gt; 的底部创建一个空 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;
    }
    

    然后创建一个组件,该组件将为其子级附加一个自定义div,由上述函数创建

    const Modal = ({children}) => {
        const target = usePortal('#react-root-div');
        return ReactDOM.createPortal(children, target);
    };
    

    然后简单地用 Modal 组件包装输入元素,它将被(几乎)附加到 DOM 树的底部。

        <Modal>
            <input {...getInputProps()} />
        </Modal>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-04
      • 1970-01-01
      • 2014-05-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多