首页 > 解决方案 > 如何控制/禁用 IOS 中用于导航的滑动快照(JS)

问题描述

我的任务是修复我的 nextjs 应用程序中的一个讨厌的错误。本质上,当您在 IOS 上使用手指滑动浏览应用程序时,页面内容会闪烁。

据我所知,浏览器会在给定时间点拍摄堆和 dom 的快照。然后,一旦您想要导航回该页面,它会在您滑动时显示该快照。一旦您完成滑动并且浏览器认为页面已完成加载,它将停止显示快照并显示页面。

坦率地说,一旦快照停止显示,我已经放弃让快照实际匹配内容。我正在寻找的是一种禁用或控制显示为空白页的快照的方法。是的,它伤害了用户体验,但我的老板更喜欢它而不是闪存。

我已经在互联网上搜索了一个解决方案,现在我正在尝试通过 webkit 源代码来了解如何实现这一点。我知道这是可以实现的,因为 Instagram 已经实现了这一点。

如果您在 safari iOS 上访问 instagram.com 并尝试滑动手指进行导航,您会看到快照只是一个白页。

如果有人对如何做到这一点有任何见解,或者至少可以为我指明正确的方向,我将不胜感激。

谢谢!

标签: iosreactjsnext.js

解决方案


我能够通过浏览 webkit 源代码来解决这个问题。

这是相关文件

第 225 行是加载快照图像的内容。因此,我们需要以某种方式让第 224 行中的条件评估为假。我发现的最简单的方法是得到这件作品:

shouldRestoreScrollPosition || (currentScrollPosition == snapshot->viewScrollPosition())

评估为假。第一部分shouldRestoreScrollPosition历史对象的 scrollRestoration 属性决定。浏览器对该属性的支持非常好,将其设置为手动将使您获得禁用图像快照的大部分方法。

只有一个问题,即该条件的第二部分。如果快照图像和窗口的滚动位置相同,scrollRestoration 将被忽略(因为它甚至不需要应用)。我使用了以下代码段,_app.tsx其中似乎可以正常工作。

    const alternator = React.useRef<number>(0);
    // Scroll slightly and alternate between pages to always invalidate image snapshot.
    // See {redacted} for explanation on this effect and the previous
    React.useEffect(() => {
        const slightScroll = () => {
            if (IOS()) {
                window.scrollTo({left: 0, top: alternator.current});
                alternator.current = Number(!alternator.current);
            }
        };

        router.events.on('routeChangeComplete', slightScroll);

        return () => router.events.off('routeChangeComplete', slightScroll);
    }, []);

这显然是一个非常 next.js 特定的片段,但想法是一样的。在向下滚动 1 个像素或不滚动之间交替,以确保在历史记录中前进或后退时滚动位置不同。

该解决方案并不完美(例如,在没有滚动的页面之间切换),但效果很好。此外,了解导致快照图像加载/不加载的确切条件意味着,如果有人看到这种情况需要改进我的解决方案,他们可以尝试其他方法使该条件评估为假或阻止线路执行更远(我个人尝试在页面之间更改设备规模的标题但无济于事)。

希望这可以避免我不得不经历的挫败感:)


推荐阅读