You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在SvelteKit中从父+page.svelte向子页面传递数据?

问题描述

我用最新版SvelteKit开发,文件采用+page.svelte、+page.js、+page.server.js格式。在nowPlaying目录下的页面拉取正在上映的电影列表,点击电影海报时会把电影信息存入pkg对象,现在想把这些数据传递到跳转后的nowPlayingMovieDetails页面并展示。

文件结构:

+ src
  |
  +-- routes
      |
      +-- nowPlaying
          |
          +-- +page.server.js
          +-- +page.svelte
          |
          +-- nowPlayingMovieDetails
              |
              +-- +page.js
              +-- +page.svelte

当前nowPlaying/+page.svelte核心代码:

<script>
  let pkg = {
      movieID: "",
      movieName: "",
      movieOverview: "",
      movieReleaseDate: "",
      moviePosterPath: "",
  }

  function acquireMovieInfo(id, name, overview, release, poster) {
        pkg = {
            movieID: id,
            movieName: name,
            movieOverview: overview,
            movieReleaseDate: release,
            moviePosterPath: poster,
        }
        console.log(pkg);
    }
</script>

<div>
    <ul>
        {#each movies_nowPlaying as movieNowPlaying}
            <li>
                <a href="/nowPlayingMovieDetails" data-movie-id={movieNowPlaying.id} on:click={() => acquireMovieInfo(movieNowPlaying.id, movieNowPlaying.original_title, movieNowPlaying.overview, movieNowPlaying.release_date, movieNowPlaying.poster_path)}><img src="http://image.tmdb.org/t/p/w500/{movieNowPlaying.poster_path}" alt="{movieNowPlaying.title} movie poster"></a>
            </li>
        {/each}
    </ul>
</div>

可行解决方案

推荐两种方案,按需选择:

方案一:通过URL参数传递电影ID(优先选,支持页面刷新)

这是最符合SvelteKit路由规范的做法,即使用户刷新详情页也能正常获取数据,稳定性更高。

1. 修改跳转链接,带上电影ID

把nowPlaying/+page.svelte里的<a>标签路径改成带ID的格式(注意路径要对应子目录结构,之前的/nowPlayingMovieDetails是错误的),同时可以去掉acquireMovieInfo的调用(不需要再存pkg):

<!-- nowPlaying/+page.svelte -->
<a href="/nowPlaying/nowPlayingMovieDetails/{movieNowPlaying.id}">
  <img src="http://image.tmdb.org/t/p/w500/{movieNowPlaying.poster_path}" alt="{movieNowPlaying.title} movie poster">
</a>

2. 把详情页改成动态路由

将nowPlaying/nowPlayingMovieDetails目录重命名为[movieId],这样SvelteKit就能捕获URL里的ID参数:

+ src
  |
  +-- routes
      |
      +-- nowPlaying
          |
          +-- +page.server.js
          +-- +page.svelte
          |
          +-- [movieId]  <!-- 原nowPlayingMovieDetails改名为这个 -->
              |
              +-- +page.server.js  <!-- 新增文件,用来请求详情 -->
              +-- +page.svelte

3. 在详情页的+page.server.js中请求电影数据

通过params获取URL里的电影ID,调用TMDB接口拉取详情:

// nowPlaying/[movieId]/+page.server.js
export async function load({ params }) {
  const movieId = params.movieId;
  // 替换成你的TMDB API密钥
  const res = await fetch(`https://api.themoviedb.org/3/movie/${movieId}?api_key=你的API密钥&language=zh-CN`);
  const movieDetails = await res.json();
  
  return {
    movieDetails
  };
}

4. 在详情页展示数据

直接使用data对象里的电影详情:

<!-- nowPlaying/[movieId]/+page.svelte -->
<script>
  export let data;
  const { movieDetails } = data;
</script>

<div class="movie-details">
  <h1>{movieDetails.title}</h1>
  <img src={`http://image.tmdb.org/t/p/w500/${movieDetails.poster_path}`} alt={movieDetails.title}>
  <p>{movieDetails.overview}</p>
  <p>上映日期:{movieDetails.release_date}</p>
</div>

方案二:通过page.state传递完整数据(无需重新请求,但刷新会丢失)

如果不想重复调用TMDB接口,可以用SvelteKit的page.state直接传递已有的pkg数据,但这种方式下刷新详情页会丢失数据,适合对刷新无要求的场景。

1. 用goto方法跳转并传递数据

在nowPlaying/+page.svelte中导入goto,修改点击逻辑,阻止默认跳转并通过state传递数据:

<!-- nowPlaying/+page.svelte -->
<script>
  import { goto } from '$app/navigation';
  let pkg = { /* 原定义不变 */ };

  function acquireMovieInfo(id, name, overview, release, poster) {
        pkg = {
            movieID: id,
            movieName: name,
            movieOverview: overview,
            movieReleaseDate: release,
            moviePosterPath: poster,
        };
        // 带state跳转
        goto('/nowPlaying/nowPlayingMovieDetails', { state: { movieData: pkg } });
    }
</script>

<!-- 修改a标签,去掉href,阻止默认跳转行为 -->
<a href="" on:click|preventDefault={() => acquireMovieInfo(movieNowPlaying.id, movieNowPlaying.original_title, movieNowPlaying.overview, movieNowPlaying.release_date, movieNowPlaying.poster_path)}>
  <img src="http://image.tmdb.org/t/p/w500/{movieNowPlaying.poster_path}" alt="{movieNowPlaying.title} movie poster">
</a>

2. 在详情页的+page.js中获取state数据

从navigation对象里取出传递的电影数据:

// nowPlaying/nowPlayingMovieDetails/+page.js
export async function load({ navigation }) {
  if (navigation?.state?.movieData) {
    return {
      movieData: navigation.state.movieData
    };
  }
  // 刷新页面时的 fallback 处理,比如返回空或跳回列表页
  return {
    movieData: null
  };
}

3. 在详情页展示数据

判断数据是否存在,然后渲染:

<!-- nowPlaying/nowPlayingMovieDetails/+page.svelte -->
<script>
  export let data;
  const { movieData } = data;
</script>

{#if movieData}
  <div class="movie-details">
    <h1>{movieData.movieName}</h1>
    <img src={`http://image.tmdb.org/t/p/w500/${movieData.moviePosterPath}`} alt={movieData.movieName}>
    <p>{movieData.movieOverview}</p>
    <p>上映日期:{movieData.movieReleaseDate}</p>
  </div>
{:else}
  <p>无法获取电影信息,请返回列表页重新选择</p>
{/if}

内容的提问来源于stack exchange,提问作者illusive_yeti

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 20:30:49