Svelte window 元素 on:load 回调未在移动版 Safari 中触发

Svelte window element on:load callback not firing in mobile Safari

我正在开发一个 Svelte 和 Sapper 静态站点,我正在将其导出并上传到服务器。 rollup.config.jspackage.jsonsapper-template on Github 中的一样,对 package.json 稍作修改以避免在 mac 上开发时出现 .DS_store 问题:

"scripts": {
  "dev": "yarn dsstore:delete && sapper dev",
  "build": "yarn dsstore:delete && sapper build --legacy",
  "export": "yarn dsstore:delete && sapper export --legacy",
  "start": "node __sapper__/build",
  "dsstore:delete": "find . -name \".DS_Store\" -delete"
}

我在主页上重复了大约十次的 svelte 组件中使用了以下代码。这是一个以高质量摄影为主要内容的网站,因此我加载了一张沉重的图像作为组件的背景图像。为了平滑图像加载体验,我首先在背景中加载一个非常轻的占位符图像,然后根据 window 大小,在顶部加载两个不同大小的背景图像之一:

<script>
    export let project;
    let { id, src, src_small } = project;

    let el;
    let breakpointCondition = "(max-width: 1000px)";
    let view;
    let imageSrc;

    const checkView = (e) => {
        console.log(document);
        el = document.getElementById(id);
        console.log(el);
        view = window.matchMedia(breakpointCondition);
        if (view.matches) {
            imageSrc = src_small;
        } else {
            imageSrc = src;
        }

        el.style.backgroundImage = `url(${imageSrc}), url('images/placeholder.png')`;   
    }

</script>

<svelte:window on:load={checkView} on:resize={checkView} />

<section id={id} >

...

<section>

<style>

    section {
        background-image: url('/images/placeholder.png');
    }

</style>

此代码在桌面浏览器上按预期工作。页面加载后,svelte window 元素变为可用,我可以查询它以加载适当的背景图像。在 ios 浏览器(移动版 Safari、Chrome 和 Firefox)上,当我导航到该页面时,javascript 的背景图像不会加载,但如果我刷新页面,它们会加载.

我试过替换:

<svelte:window on:load={console.log('load')} on:resize={console.log('resize')} />

并发现 window.onload 和 window.onresize 事件在页面加载时同时在桌面和移动浏览器上触发。奇怪的是,当我在页面加载后调整 window 大小时没有日志出现,但 window.matchMedia 方法似乎继续执行其工作并且图像交换发生在适当的断点。

当我将日志放在 checkView 回调函数的开头时,我看到虽然 onload 事件正在触发,但当页面首次在 [=51] 上加载时该函数并未触发=] 移动浏览器。当我在 ios 浏览器上重新加载页面时,回调函数会触发,我得到了预期的结果。

为什么会发生这种情况,我该如何解决?此方法在桌面上运行良好。

更新: 使用 onMount 在页面加载时触发 checkView

<svelte:window on:resize={checkView} />

当 window 调整大小时有效。问题仍然悬而未决,以防有人知道原因

<svelte:window on:load={checkView}>

不会在移动版 Safari 的初始页面加载时触发回调。

据我所知,<svelte:window /> 可让您收听 window 事件,因此您可以使用它,例如,通过 on:resize 收听 'resize' 事件。 至于on:load

(see MDN's Window: load event:)

The load event is fired when the whole page has loaded, including all dependent resources such as stylesheets and images. This is in contrast to DOMContentLoaded, which is fired as soon as the page DOM has been loaded, without waiting for resources to finish loading.

因此,如果页面已加载且加载事件已被触发,则监听此事件是多余的,并且永远不会调用回调。 当页面真正完成加载时检查您的代码 (index.html?)

如果您想确保特定 Svelte 组件中的 DOM 元素已完成渲染,Svelte 建议使用它们的 onMount(() => {}) 回调:

<script>
    export let project;
    let { id, src, src_small } = project;

    let el;
    let breakpointCondition = "(max-width: 1000px)";
    let view;
    let imageSrc;

    onMount(() => {
        console.log(document);
        el = document.getElementById(id);
        console.log(el);
        view = window.matchMedia(breakpointCondition);
        if (view.matches) {
            imageSrc = src_small;
        } else {
            imageSrc = src;
        }

        el.style.backgroundImage = `url(${imageSrc}), url('images/placeholder.png')`;   
    })

</script>

<section id={id} >
...
</section>

<style>

    section {
        background-image: url('/images/placeholder.png');
    }

</style>