提问人:Jay0813 提问时间:9/19/2023 最后编辑:Jay0813 更新时间:9/20/2023 访问量:87
如何使用api请求在sveltekit中实现多个预输入搜索输入?
How to implement multiple typeahead search input in sveltekit with api request?
问:
我正在尝试实现一项功能,每次用户在输入字段中键入时,都会发出 API 请求,结果会直接显示在输入下方。它类似于预输入或自动完成功能。虽然我可能直接从客户端发出请求并显示结果,但我需要在服务器端处理 API 请求。这是因为所有请求都必须在标头中包含令牌,并且存储令牌的 cookie 设置为 httpOnly:true。因此,我无法从客户端访问此 cookie。有人可以指导我如何实现这一目标吗? 欢迎任何建议。谢谢
<script lang="ts">
import { Button, Input, Label } from 'flowbite-svelte';
export let data;
let taskId = '';
const onChange = async () => {};
</script>
<div class="max-w-screen-md mx-auto p-6 space-y-8">
<div class="bg-white shadow-md rounded-lg p-6">
<div class="text-center mb-8">
<h2 class="text-2xl bold">Task Form</h2>
</div>
<div class="relative">
<Label class="block mb-1">Task ID</Label>
<Input
label="Email"
id="email"
name="email"
bind:value={taskId}
on:change={onChange}
required
placeholder="Task id..."
/>
<br />
<Label class="block mb-1">유저 닉네임</Label>
<Input label="nickname" id="nickname" name="nickname" required placeholder="nickname..." />
</div>
</div>
<Button type="submit">Create</Button>
</div>
答:
问题陈述:我的目标是实现一个功能,每次用户输入字段时,都会触发一个 API 请求,结果显示在输入的正下方。请务必注意,API 请求需要在服务器端处理,而不是直接从客户端处理。这是因为必须在请求标头中包含令牌,该令牌存储在设置为 httpOnly: true 的 cookie 中。因此,无法从客户端访问它。
客户端代码:
为了避免在每次击键时立即发出 API 请求,我采用了去抖动功能。这可确保函数仅在用户停止键入指定持续时间后执行。
我使用单独的状态变量来管理 taskId 和 nickname 的输入值。
在每个输入上,都会调用去抖动包装的 API 调用函数 和 。
结果存储在 taskResults 和 nicknameResults 中,随后显示给用户。_handleTaskInput
_handleNicknameInput
服务器端代码:
这段代码处理从客户端发送的请求。 它处理 /api/task 端点的 POST 请求。 taskId 值是从请求正文中提取的,并基于该值生成并返回模拟结果数据。 在实际方案中,此部分通常会查询外部 API 或数据库来获取实际数据。
注意:当从客户端对“/api/task”进行 fetch 调用时,它 对应于执行位于 /routes/api/task/+server.ts。
这是我的代码。
// client side
<script lang="ts">
import debounce from '$lib/utils/debounce';
import { Button, Input, Label } from 'flowbite-svelte';
let taskId = '';
let nickname = '';
let nicknameResults: any[];
let taskResults: any[];
async function _getTaskList() {
const response = await fetch('/api/task', {
method: 'POST',
body: JSON.stringify({ taskId }),
headers: {
'content-type': 'application/json'
}
});
taskResults = await response.json();
}
async function _getNicknameList() {
const response = await fetch('/api/user', {
method: 'POST',
body: JSON.stringify({ nickname }),
headers: {
'content-type': 'application/json'
}
});
nicknameResults = await response.json();
}
function _selectTaskResult(result: { id: number; name: string }) {
taskId = result.id.toString();
taskResults = []; // 선택한 후 결과 목록을 숨깁니다.
}
function _selectNicknameResult(result: { id: number; name: string }) {
nickname = result.id.toString();
nicknameResults = []; // 선택한 후 결과 목록을 숨깁니다.
}
const _debouncedTaskList = debounce(_getTaskList, 300);
const _debouncedNicknameList = debounce(_getNicknameList, 300);
function _handleTaskInput(event: Event) {
_debouncedTaskList();
}
function _handleNicknameInput(event: Event) {
_debouncedNicknameList();
}
$: console.log({ nickname });
</script>
<div class="max-w-screen-md mx-auto p-6 space-y-8">
<div class="bg-white shadow-md rounded-lg p-6 min-h-[800px]">
<div class="text-center mb-8">
<h2 class="text-2xl bold">Create Task</h2>
</div>
<div class="relative">
<div class="relative">
<Label class="block mb-1">taskId</Label>
<Input
label="taskId"
id="taskId"
name="taskId"
bind:value={taskId}
on:input={_handleTaskInput}
required
placeholder="task id"
/>
{#if taskResults && taskResults.length > 0}
<div class="absolute w-full top-16 mt-2 bg-white border border-gray-300 z-10">
{#each taskResults as taskResult}
<div
on:keydown={() => _selectTaskResult(taskResult)}
on:click={() => _selectTaskResult(taskResult)}
class="cursor-pointer hover:bg-gray-200 p-2"
>
{taskResult.id}
</div>
{/each}
</div>
{/if}
</div>
<br />
<div class="relative">
<Label class="block mb-1">nickname</Label>
<Input
label="nickname"
id="nickname"
name="nickname"
bind:value={nickname}
on:input={_handleNicknameInput}
required
placeholder="nickname"
/>
{#if nicknameResults && nicknameResults.length > 0}
<div class="absolute w-full top-16 mt-2 bg-white border border-gray-300 z-10">
{#each nicknameResults as nicknameResult}
<div
on:keydown={() => _selectNicknameResult(nicknameResult)}
on:click={() => _selectNicknameResult(nicknameResult)}
class="cursor-pointer hover:bg-gray-200 p-2"
>
{nicknameResult.id}
</div>
{/each}
</div>
{/if}
</div>
</div>
</div>
<Button type="submit">Create</Button>
</div>
// server side
// path : /routes/task/+server.ts
import { json } from '@sveltejs/kit';
import type { RequestHandler } from './$types';
export const POST: RequestHandler = async ({ request }) => {
const { taskId } = await request.json();
if (!taskId) return json([]);
// Api call here
console.log({ taskId });
const result = [
{ id: 1, name: taskId },
{ id: 2, name: taskId },
{ id: 3, name: taskId },
{ id: 4, name: taskId },
{ id: 5, name: taskId },
{ id: 6, name: taskId }
];
return json(result);
};
评论