SolidJS按钮触发多参数表单提交及相关技术问题咨询
问题解答
1. 实现按钮点击触发搜索结果获取
核心思路是用Signal存储搜索关键词,通过按钮点击事件更新这个Signal,再结合SolidJS的createResource或手动Fetch触发请求:
方案一:使用createResource(推荐,自带状态管理)
在useSearch.ts中封装逻辑:
import { createSignal, createResource } from 'solid-js'; export interface SearchRequest { q: string; } export interface SearchResponse { results: Array<{ id: string; title: string }>; total: number; } export function useSearch() { // 存储触发请求的关键词(仅点击按钮时更新) const [query, setQuery] = createSignal(''); // 存储输入框实时值(输入时更新,不触发请求) const [inputValue, setInputValue] = createSignal(''); // 搜索请求函数 const fetchSearch = async (q: string): Promise<SearchResponse> => { if (!q.trim()) return { results: [], total: 0 }; const res = await fetch(`http://localhost:7070/search?q=${encodeURIComponent(q)}`); if (!res.ok) throw new Error('请求失败'); return res.json(); }; // 以query为依赖,仅当query变化时触发请求 const [searchResult] = createResource(query, fetchSearch); // 按钮点击时同步输入框值到query,触发资源加载 const handleSearch = () => { setQuery(inputValue()); console.log('提交搜索:', inputValue()); }; return { inputValue, setInputValue, handleSearch, searchResult, }; }
组件中使用:
import { useSearch } from './useSearch'; export function SearchComponent() { const { inputValue, setInputValue, handleSearch, searchResult } = useSearch(); return ( <div> <input type="text" value={inputValue()} onChange={(e) => setInputValue(e.target.value)} placeholder="输入搜索关键词" /> <button onClick={handleSearch}>搜索</button> {searchResult.loading && <div>加载中...</div>} {searchResult.error && <div>搜索失败:{searchResult.error.message}</div>} {searchResult()?.results.map(item => ( <div key={item.id}>{item.title}</div> ))} </div> ); }
方案二:手动Fetch(适合简单场景)
如果不想用createResource,可直接用Signal管理结果和状态:
// useSearch.ts import { createSignal } from 'solid-js'; export function useSearch() { const [inputValue, setInputValue] = createSignal(''); const [results, setResults] = createSignal<SearchResponse | null>(null); const [loading, setLoading] = createSignal(false); const [error, setError] = createSignal<string | null>(null); const handleSearch = async () => { const q = inputValue().trim(); if (!q) return; setLoading(true); setError(null); console.log('提交搜索:', q); try { const res = await fetch(`http://localhost:7070/search?q=${encodeURIComponent(q)}`); if (!res.ok) throw new Error('请求失败'); const data = await res.json(); setResults(data); } catch (err) { setError(err instanceof Error ? err.message : '未知错误'); } finally { setLoading(false); } }; return { inputValue, setInputValue, handleSearch, results, loading, error, }; }
2. 正确反序列化为SearchResponse类型
TypeScript类型仅做编译时检查,运行时需确保数据结构符合预期,推荐两种方式:
方式一:类型断言(简单,无运行时检查)
适合信任后端返回结构的场景,直接添加类型断言:
const data = await res.json() as SearchResponse;
方式二:运行时验证(推荐,更安全)
用zod库做运行时结构验证,同时自动生成TypeScript类型:
- 安装依赖:
npm install zod - 定义Schema并验证:
import { z } from 'zod'; // 定义响应结构的Zod Schema const SearchResponseSchema = z.object({ results: z.array(z.object({ id: z.string(), title: z.string(), })), total: z.number(), }); // 自动生成TypeScript类型 export type SearchResponse = z.infer<typeof SearchResponseSchema>; // 请求时验证数据 const fetchSearch = async (q: string): Promise<SearchResponse> => { const res = await fetch(`http://localhost:7070/search?q=${encodeURIComponent(q)}`); if (!res.ok) throw new Error('请求失败'); const rawData = await res.json(); // 验证结构,不符合则抛出错误 return SearchResponseSchema.parse(rawData); };
3. SolidJS中Signals与Resources的最佳实践
- Signal存同步状态:输入框值、筛选条件、UI开关等交互状态,用Signal管理,保证响应式更新。
- Resource处理异步请求:Resource自带
loading/error/data状态,无需手动维护,自动追踪依赖变化触发请求,组件卸载时自动取消请求。 - 封装自定义Hook:将异步逻辑(如搜索、列表加载)封装在单独的
useXXX.ts中,组件只负责渲染和交互,提高代码复用性。 - 控制请求触发时机:通过Resource的source参数控制请求触发(如仅点击按钮时更新source),避免不必要的请求。
- 处理状态反馈:始终展示加载提示、错误信息,避免用户困惑。
- 避免无效请求:比如关键词为空时不触发请求,减少后端压力。
- 设置初始值:创建Resource时可传入
initialValue,避免渲染时出现null/undefined的情况。
内容的提问来源于stack exchange,提问作者djsumdog
相关产品推荐
相关产品推荐

