Svelte实现多按钮触发Fetch请求(取消初始自动请求)
Svelte多按钮按需请求数据实现方案
原代码问题分析
你当前的fetch.js中,fetchStore函数在创建后会自动调用内部的get()方法,导致页面加载时就发起请求。要实现点击对应按钮才触发请求,需要去掉自动调用逻辑,并让请求触发逻辑由按钮点击事件控制。
核心修改原理
- 移除
fetchStore内部的自动get()调用,让请求仅在外部主动调用时触发。 - 让
get()方法支持动态传入URL,适配不同按钮的请求目标。 - 可选择使用共享状态或独立状态:共享状态适合所有按钮复用同一展示区域,独立状态适合每个按钮对应单独的结果展示。
实现方案
方案1:共享状态(所有按钮共用同一结果区域)
修改fetch.js
import { writable } from 'svelte/store' export default function fetchStore(initialUrl = null) { const loading = writable(false) const error = writable(false) const data = writable({}) let currentUrl = initialUrl async function get(url = currentUrl) { if (!url) return loading.set(true) error.set(false) try { const response = await fetch(url) if (!response.ok) throw new Error(`请求失败:${response.status}`) data.set(await response.json()) currentUrl = url } catch(e) { error.set(e.message || e.toString()) } loading.set(false) } // 移除自动调用get(),改为外部触发 return [ data, loading, error, get ] }
修改App.Svelte
<script> import fetchStore from './fetch.js' // 创建一个共享的fetch状态实例 const [data, loading, error, get] = fetchStore() // 定义按钮对应的请求配置 const requestItems = [ { label: '获取卢克数据', url: 'https://www.swapi.tech/api/people/1' }, { label: '获取莱娅数据', url: 'https://www.swapi.tech/api/people/5' }, { label: '获取维达数据', url: 'https://www.swapi.tech/api/people/4' } ] </script> <div class="button-container"> {#each requestItems as item} <button on:click={() => get(item.url)}> {item.label} </button> {/each} </div> {#if $loading} <p>加载中...</p> {:else if $error} <p style="color: #dc2626;">错误:{$error}</p> {:else if Object.keys($data).length > 0} <pre>{JSON.stringify($data, null, 2)}</pre> {:else} <p>点击上方按钮获取数据</p> {/if} <style> .button-container { gap: 0.5rem; display: flex; margin: 1rem 0; } </style>
方案2:独立状态(每个按钮对应单独的结果区域)
如果需要每个按钮的加载、错误、数据状态独立展示,可为每个请求创建单独的fetchStore实例:
App.Svelte代码
<script> import fetchStore from './fetch.js' // 为每个请求创建独立的状态实例 const requestItems = [ { label: '卢克', url: 'https://www.swapi.tech/api/people/1', ...fetchStore() }, { label: '莱娅', url: 'https://www.swapi.tech/api/people/5', ...fetchStore() }, { label: '维达', url: 'https://www.swapi.tech/api/people/4', ...fetchStore() } ] </script> {#each requestItems as item} <div class="card"> <button on:click={() => item.get(item.url)}> 获取{item.label}数据 </button> {#if $item.loading} <p>加载中...</p> {:else if $item.error} <p style="color: #dc2626;">错误:{$item.error}</p> {:else if Object.keys($item.data).length > 0} <pre>{JSON.stringify($item.data, null, 2)}</pre> {/if} </div> {/each} <style> .card { margin: 1rem 0; padding: 1rem; border: 1px solid #e5e7eb; border-radius: 6px; } </style>
内容的提问来源于stack exchange,提问作者user1513388
相关产品推荐
相关产品推荐

