文档
Nuxt 全栈代办事项 + API
目标
展示 Nuxt 全栈能力:前端代办 UI + server/api/ 后端接口 + useFetch 调用。
完整代码
server/api/todos.ts
// Nuxt Nitro API — 内存存储示例
let todos: { id: number; text: string; done: boolean }[] = [
{ id: 1, text: '学习 Nuxt 3', done: true },
{ id: 2, text: '完成毕设', done: false },
]
let nextId = 3
export default defineEventHandler(async (event) => {
const method = event.method
// GET /api/todos
if (method === 'GET') {
return todos
}
// POST /api/todos
if (method === 'POST') {
const body = await readBody(event)
const todo = { id: nextId++, text: body.text, done: false }
todos.push(todo)
return todo
}
// DELETE /api/todos?id=1
if (method === 'DELETE') {
const id = Number(getQuery(event).id)
todos = todos.filter(t => t.id !== id)
return { success: true }
}
throw createError({ statusCode: 405 })
})
pages/index.vue
<script setup lang="ts">
const newTodo = ref('')
// useFetch 在服务端和客户端都能工作
const { data: todos, refresh } = await useFetch('/api/todos')
const { data: serverInfo } = await useFetch('/api/info')
async function addTodo() {
const text = newTodo.value.trim()
if (!text) return
await $fetch('/api/todos', { method: 'POST', body: { text } })
newTodo.value = ''
refresh()
}
async function removeTodo(id: number) {
await $fetch(`/api/todos?id=${id}`, { method: 'DELETE' })
refresh()
}
async function toggleTodo(todo: any) {
// 简化 toggle,实际应加 PATCH
todo.done = !todo.done
}
</script>
<template>
<div class="container">
<h1>🏔️ Nuxt 全栈代办</h1>
<!-- 服务端信息 -->
<div class="server-info">
<span>🖥️ 服务端信息: {{ serverInfo }}</span>
</div>
<!-- 输入 -->
<form @submit.prevent="addTodo" class="input-group">
<input v-model="newTodo" placeholder="输入新任务..." class="todo-input" />
<button type="submit">添加</button>
</form>
<!-- 列表 -->
<ul class="todo-list">
<li v-for="todo in todos" :key="todo.id">
<span @click="toggleTodo(todo)" style="cursor:pointer">
{{ todo.done ? '✅' : '⬜' }}
<span :class="{ done: todo.done }">{{ todo.text }}</span>
</span>
<button @click="removeTodo(todo.id)" class="del-btn">🗑️</button>
</li>
</ul>
</div>
</template>
<style scoped>
.container { max-width: 480px; margin: 2rem auto; font-family: system-ui; }
h1 { color: #00dc82; }
.server-info { background: #f0fdf4; padding: 8px 12px; border-radius: 8px; font-size: 0.85rem; margin-bottom: 1rem; }
.input-group { display: flex; gap: 8px; margin-bottom: 1rem; }
.todo-input { flex: 1; padding: 8px 12px; border: 2px solid #e2e8f0; border-radius: 8px; }
button { padding: 8px 16px; background: #00dc82; color: white; border: none; border-radius: 8px; cursor: pointer; }
.todo-list { list-style: none; padding: 0; }
.todo-list li { display: flex; justify-content: space-between; padding: 8px 0; border-bottom: 1px solid #f1f5f9; }
.done { text-decoration: line-through; color: #94a3b8; }
.del-btn { background: none; border: none; cursor: pointer; }
</style>
server/api/info.ts
export default defineEventHandler(() => ({
runtime: 'Nitro',
timestamp: new Date().toISOString(),
node: process.version,
}))
运行
npm run dev
# → http://localhost:3000
预期输出
- 服务端信息显示在顶部(SSR 渲染)
- 代办列表从
/api/todos获取 - 添加/删除实时刷新,API 和前端一体