javascript - SvelteKit 渲染随机 Prop 在服务器和客户端之间是不同的

标签 javascript server-side-rendering svelte sveltekit

我想在 SvelteKit 中制作一个具有随机参数的组件。问题在于,当页面在服务器端呈现时与页面变为水合时,此参数所取的值是不同的。
例如,考虑这个组件:

<script>
    export let t = Math.random() * 90
    export let l = Math.random() * 90
</script>

<div class="box" style="--t: {t}vh; --l: {l}vw;"></div>

<style>
    .box {
        position: fixed;
        top: var(--t); left: var(--l);
        width: 10vw; height: 10vh;
        background-color: black;
        transition: all 1s;
    }
</style>
当页面在服务器上渲染时,tl取一些随机值,结果以 HTML 格式返回给浏览器。然而,一旦页面变得湿润,tl采取不同的值(value)观。结果,盒子移动了。
我不想让盒子移动;而是,我希望服务器返回的随机值也被客户端使用所以没有一闪而过的风格变化。如果页面通过页内路由器导航,一切都很好;当页面被服务器渲染时,框移动。
如果我导出 load,结果是一样的功能。 SvelteKit 有没有办法让服务器和客户端就随机值达成一致?

最佳答案

你有几个选择:

  • 在 onMount 中设置随机数,以便它们仅在客户端上设置。但是,这将导致 FOUC,因为该框不会被服务器渲染。

  • <script>
      import { onMount } from 'svelte';
    
      let t, l;
    
      onMount(() => {
        t = Math.random() * 90;
        l = Math.random() * 90;
      })
    </script>
    
    {#if t && l }
    <div class="box" style="--t: {t}vh; --l: {l}vw;"></div>
    {/if}
    
    <style>
        .box {
            position: fixed;
            top: var(--t); left: var(--l);
            width: 10vw; height: 10vh;
            background-color: black;
            transition: all 1s;
        }
    </style>
    
  • 在加载函数中获取的服务器端点内生成随机数。由于 SvelteKit 在负载中缓存了获取的结果,因此应该在客户端和服务器上使用相同的随机数。

  • // random.json.js
    export async function get() {
      return {
        body: {
          t: Math.random() * 90,
          l: Math.random() * 90,
        },
      };
    }
    
    <!-- index.svelte -->
    <script context="module">
      export async function load({ fetch }) {
        // this will be cached, so it will be the same on client & server
        const result = await fetch('/random.json');
        const { t, l } = await result.json();
        return {
          props: {
            t, l
          }
        }
      }
    </script>
    
    <script>
        export let t;
        export let l;
    </script>
    
    <div class="box" style="--t: {t}vh; --l: {l}vw;"></div>
    
    <style>
        .box {
            position: fixed;
            top: var(--t); left: var(--l);
            width: 10vw; height: 10vh;
            background-color: black;
            transition: all 1s;
        }
    </style>
    
    就个人而言,我更喜欢第二种选择,因为没有 FOUC。

    关于javascript - SvelteKit 渲染随机 Prop 在服务器和客户端之间是不同的,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70714461/

    相关文章:

    javascript - 使用 Grunt 和 Webpack 的结构

    javascript - 在 ReactJs 中悬停时替换元素

    javascript - 选中相应的复选框时,我无法获取两个输入框的值

    typescript - 获取 Ts/Js 文件中 Svelte 存储变量的当前值

    typescript - 如何在标记部分进行类型注释

    SvelteKit:CSS 中引用的静态资源的开发/构建和路径问题

    javascript - React 生命周期事件 - 子组件继承旧状态 Prop

    css - 为什么我不能为我的 React 服务器端渲染应用程序导入 CSS 文件?

    javascript - 在 React 应用程序中结合 SSR 和 CSR

    javascript - 如何将数据从组件传递到 getServerSideProps