第 5 章:个人主页开发
约 4929 字大约 16 分钟
2025-12-19
本章学习目标
- 学习页面布局(Header/Main/Footer)
- 理解组件拆分的思想
- 快速上手 Tailwind CSS
- 理解 Tailwind CSS 的优缺点与原生 CSS 的混合使用
- 创建个人信息展示页面
- 🎉 成果:一个漂亮的个人主页!
前面几章我们学会了前后端交互,页面也能动起来了。但说实话,现在的页面...有点丑。
这一章我们要让它变好看!
本章结束后你会得到什么
一个专业的个人主页:有清晰的页面布局、漂亮的样式、可复用的组件——可以发给朋友炫耀的那种!
5.1 认识页面布局
5.1.1 经典的三段式布局
打开任何一个网站,你会发现大多数都是这样的结构:
就连我们这个文档的首页也是这样的,你可以点回去看看首页
为什么都长这样?
因为这是用户最习惯的布局方式:
- Header:放 Logo、导航菜单,让用户知道"我在哪"
- Main:放核心内容,用户来这里是为了看这个
- Footer:放版权信息、联系方式等次要内容
5.1.2 创建布局组件
在 Nuxt 中,我们用 layouts 来定义页面布局。
首先,在 frontend/app/ 目录下创建 layouts 文件夹,然后创建 default.vue:
<!-- frontend/app/layouts/default.vue -->
<template>
<div class="layout">
<!-- 顶部导航 -->
<header class="header">
<div class="header-content">
<div class="logo">🚀 我的博客</div>
<nav class="nav">
<a href="/" class="nav-link">首页</a>
<a href="/about" class="nav-link">关于</a>
<a href="/blog" class="nav-link">博客</a>
</nav>
</div>
</header>
<!-- 主要内容区域 -->
<main class="main">
<slot />
</main>
<!-- 底部信息 -->
<footer class="footer">
<p>© 2025 我的博客 | 用 ❤️ 和 Nuxt + FastAPI 构建</p>
</footer>
</div>
</template>
<style scoped>
.layout {
min-height: 100vh;
display: flex;
flex-direction: column;
}
.header {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
padding: 1rem 0;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
}
.header-content {
max-width: 1200px;
margin: 0 auto;
padding: 0 2rem;
display: flex;
justify-content: space-between;
align-items: center;
}
.logo {
font-size: 1.5rem;
font-weight: bold;
}
.nav {
display: flex;
gap: 2rem;
}
.nav-link {
color: white;
text-decoration: none;
font-weight: 500;
transition: opacity 0.2s;
}
.nav-link:hover {
opacity: 0.8;
}
.main {
flex: 1;
max-width: 1200px;
margin: 0 auto;
padding: 2rem;
width: 100%;
box-sizing: border-box;
}
.footer {
background: #2c3e50;
color: #ecf0f1;
text-align: center;
padding: 1.5rem;
margin-top: auto;
}
</style><slot /> 是什么?
<slot /> 是 Vue 的插槽,表示"这里放子组件的内容"。
当你的页面使用这个布局时,页面的内容会自动填充到 <slot /> 的位置。
5.1.3 应用布局
现在修改 frontend/app/app.vue,让它使用布局:
<!-- frontend/app/app.vue -->
<template>
<NuxtLayout>
<NuxtPage />
</NuxtLayout>
</template>保存后刷新页面,你应该能看到顶部导航栏和底部信息栏了!
看到效果了吗?
如果页面没有变化,检查一下:
- 文件路径是否正确:
app/layouts/default.vue - 是否保存了所有文件
- 开发服务器是否在运行
5.2 组件拆分
5.2.1 为什么要拆分组件?
现在我们的 default.vue 布局文件已经有 100 多行了。如果继续往里面加功能,很快就会变成一个难以维护的"巨型文件"。
组件化思想
把大文件拆成小文件,每个文件只做一件事。
好处:
- 易读:打开文件就知道它是干什么的
- 易改:改 Header 不用担心影响 Footer
- 可复用:同一个组件可以在多个地方使用
5.2.2 创建组件目录
在 frontend/app/ 下创建 components 目录,然后创建三个组件:
AppHeader.vue:
<!-- frontend/app/components/AppHeader.vue -->
<template>
<header class="header">
<div class="header-content">
<NuxtLink to="/" class="logo">🚀 我的博客</NuxtLink>
<nav class="nav">
<NuxtLink to="/" class="nav-link">首页</NuxtLink>
<NuxtLink to="/about" class="nav-link">关于</NuxtLink>
<NuxtLink to="/blog" class="nav-link">博客</NuxtLink>
</nav>
</div>
</header>
</template>
<style scoped>
.header {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
padding: 1rem 0;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
position: sticky;
top: 0;
z-index: 100;
}
.header-content {
max-width: 1200px;
margin: 0 auto;
padding: 0 2rem;
display: flex;
justify-content: space-between;
align-items: center;
}
.logo {
font-size: 1.5rem;
font-weight: bold;
color: white;
text-decoration: none;
}
.nav {
display: flex;
gap: 2rem;
}
.nav-link {
color: white;
text-decoration: none;
font-weight: 500;
padding: 0.5rem 1rem;
border-radius: 0.5rem;
transition: background 0.2s;
}
.nav-link:hover {
background: rgba(255, 255, 255, 0.1);
}
/* 当前页面高亮 */
.nav-link.router-link-active {
background: rgba(255, 255, 255, 0.2);
}
</style>AppFooter.vue:
<!-- frontend/app/components/AppFooter.vue -->
<template>
<footer class="footer">
<div class="footer-content">
<div class="footer-links">
<a href="https://github.com" target="_blank" class="footer-link">
GitHub
</a>
<span class="divider">•</span>
<a href="mailto:hello@example.com" class="footer-link">
联系我
</a>
</div>
<p class="copyright">
© {{ currentYear }} 我的博客 | 用 ❤️ 和 Nuxt + FastAPI 构建
</p>
</div>
</footer>
</template>
<script setup>
const currentYear = new Date().getFullYear()
</script>
<style scoped>
.footer {
background: #2c3e50;
color: #ecf0f1;
padding: 2rem;
}
.footer-content {
max-width: 1200px;
margin: 0 auto;
text-align: center;
}
.footer-links {
margin-bottom: 1rem;
}
.footer-link {
color: #3498db;
text-decoration: none;
transition: color 0.2s;
}
.footer-link:hover {
color: #5dade2;
}
.divider {
margin: 0 1rem;
color: #7f8c8d;
}
.copyright {
color: #95a5a6;
font-size: 0.9rem;
}
</style>5.2.3 简化布局文件
现在修改 default.vue,使用我们创建的组件:
<!-- frontend/app/layouts/default.vue -->
<template>
<div class="layout">
<AppHeader />
<main class="main">
<slot />
</main>
<AppFooter />
</div>
</template>
<style scoped>
.layout {
min-height: 100vh;
display: flex;
flex-direction: column;
}
.main {
flex: 1;
max-width: 1200px;
margin: 0 auto;
padding: 2rem;
width: 100%;
box-sizing: border-box;
}
</style>Nuxt 自动导入
注意我们没有写 import AppHeader from '~/components/AppHeader.vue'。
Nuxt 会自动扫描 components 目录,自动导入里面的组件。这就是 Nuxt 的"约定优于配置"理念。
布局文件从 100 多行变成了 30 行,清爽多了!
5.3 Tailwind CSS 快速上手
5.3.1 为什么用 Tailwind?
你可能注意到,我们写了很多重复的 CSS:
display: flex写了好多次padding、margin到处都是- 颜色值需要记住
#667eea、#764ba2...
Tailwind CSS 是什么?
Tailwind 是一个"原子化 CSS"框架。它提供了一堆预定义的小类名,你可以直接在 HTML 中使用:
<!-- 传统写法 -->
<div style="display: flex; padding: 1rem; background: blue;">
<!-- Tailwind 写法 -->
<div class="flex p-4 bg-blue-500">好处:不用写 CSS 文件,不用想类名,直接在模板里搞定样式。
5.3.2 安装 Tailwind CSS
Nuxt 有官方的 Tailwind 模块,安装很简单:
cd frontend
pnpm add -D @nuxtjs/tailwindcss然后修改 nuxt.config.ts,添加模块:
// frontend/nuxt.config.ts
export default defineNuxtConfig({
modules: [
'@nuxtjs/tailwindcss',
// ... 其他模块
],
})重启开发服务器:
pnpm run dev5.3.3 Tailwind 常用类名速查
不用背,用的时候查就行
Tailwind 有很多类名,但你不需要全部记住。用的时候查文档,或者让 AI 帮你写。
这里列出最常用的,方便你快速上手:
布局相关:
| 类名 | 作用 | 等效 CSS |
|---|---|---|
flex | 弹性布局 | display: flex |
grid | 网格布局 | display: grid |
justify-center | 水平居中 | justify-content: center |
items-center | 垂直居中 | align-items: center |
gap-4 | 间距 | gap: 1rem |
间距相关:
| 类名 | 作用 | 等效 CSS |
|---|---|---|
p-4 | 内边距 | padding: 1rem |
px-4 | 左右内边距 | padding-left/right: 1rem |
py-4 | 上下内边距 | padding-top/bottom: 1rem |
m-4 | 外边距 | margin: 1rem |
mt-4 | 上外边距 | margin-top: 1rem |
尺寸相关:
| 类名 | 作用 | 等效 CSS |
|---|---|---|
w-full | 宽度 100% | width: 100% |
h-screen | 高度 100vh | height: 100vh |
max-w-4xl | 最大宽度 | max-width: 56rem |
min-h-screen | 最小高度 | min-height: 100vh |
颜色相关:
| 类名 | 作用 |
|---|---|
bg-blue-500 | 蓝色背景 |
text-white | 白色文字 |
text-gray-600 | 灰色文字 |
border-gray-200 | 灰色边框 |
其他常用:
| 类名 | 作用 |
|---|---|
rounded-lg | 圆角 |
shadow-lg | 阴影 |
hover:bg-blue-600 | 悬停效果 |
transition | 过渡动画 |
5.3.4 用 Tailwind 重写 Header
让我们用 Tailwind 重写 AppHeader.vue:
<!-- frontend/app/components/AppHeader.vue -->
<template>
<header class="bg-gradient-to-r from-indigo-500 to-purple-600 text-white py-4 shadow-lg sticky top-0 z-50">
<div class="max-w-6xl mx-auto px-6 flex justify-between items-center">
<NuxtLink to="/" class="text-2xl font-bold hover:opacity-80 transition">
🚀 我的博客
</NuxtLink>
<nav class="flex gap-6">
<NuxtLink
to="/"
class="px-4 py-2 rounded-lg hover:bg-white/10 transition font-medium"
>
首页
</NuxtLink>
<NuxtLink
to="/about"
class="px-4 py-2 rounded-lg hover:bg-white/10 transition font-medium"
>
关于
</NuxtLink>
<NuxtLink
to="/blog"
class="px-4 py-2 rounded-lg hover:bg-white/10 transition font-medium"
>
博客
</NuxtLink>
</nav>
</div>
</header>
</template>注意看!
原来需要 50+ 行 CSS 的组件,现在只需要模板里的几个类名!
而且这些类名都是"自解释"的:
bg-gradient-to-r→ 背景渐变,从左到右from-indigo-500 to-purple-600→ 从靛蓝色到紫色sticky top-0→ 粘性定位,距顶部 0hover:bg-white/10→ 悬停时白色背景,10% 透明度
5.3.5 用 Tailwind 重写 Footer
<!-- frontend/app/components/AppFooter.vue -->
<template>
<footer class="bg-gray-800 text-gray-300 py-8">
<div class="max-w-6xl mx-auto px-6 text-center">
<div class="mb-4 flex justify-center gap-6">
<a
href="https://github.com"
target="_blank"
class="text-blue-400 hover:text-blue-300 transition"
>
GitHub
</a>
<span class="text-gray-600">•</span>
<a
href="mailto:hello@example.com"
class="text-blue-400 hover:text-blue-300 transition"
>
联系我
</a>
</div>
<p class="text-gray-500 text-sm">
© {{ currentYear }} 我的博客 | 用 ❤️ 和 Nuxt + FastAPI 构建
</p>
</div>
</footer>
</template>
<script setup>
const currentYear = new Date().getFullYear()
</script>5.3.6 更新布局文件
<!-- frontend/app/layouts/default.vue -->
<template>
<div class="min-h-screen flex flex-col bg-gray-50">
<AppHeader />
<main class="flex-1 max-w-6xl mx-auto px-6 py-8 w-full">
<slot />
</main>
<AppFooter />
</div>
</template>现在整个布局文件只有 10 几行,而且没有 <style> 部分!
5.3.7 Tailwind 的缺点与混合使用
Tailwind 不是万能的!
虽然 Tailwind 很香,但它也有明显的缺点:
缺点一:类名太长,模板变得难读
<!-- 这一行看着头疼吗? -->
<button class="px-4 py-2 bg-indigo-600 text-white rounded-lg hover:bg-indigo-700 focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 transition-all duration-200 disabled:opacity-50 disabled:cursor-not-allowed">
提交
</button>缺点二:不利于复用和维护 如果你有 10 个按钮都是同样的样式,用 Tailwind 就要复制 10 次同样的类名。想改颜色?要改 10 个地方。
缺点三:团队协作时样式不统一 每个人可能用不同的类名组合实现同样的效果,代码风格难以统一。
5.3.8 原生 CSS 的优势
相比之下,原生 CSS 在某些场景更有优势:
<template>
<!-- 干净清爽的模板 -->
<button class="btn btn-primary">提交</button>
<button class="btn btn-secondary">取消</button>
</template>
<style scoped>
/* 可复用的按钮样式 */
.btn {
padding: 0.5rem 1rem;
border-radius: 0.5rem;
font-weight: 500;
transition: all 0.2s;
}
.btn-primary {
background: #4f46e5;
color: white;
}
.btn-primary:hover {
background: #4338ca;
}
.btn-secondary {
background: #e5e7eb;
color: #374151;
}
</style>原生 CSS 的优势
- 模板简洁:类名短,一眼就能看出元素的作用
- 易于复用:定义一次,到处使用
- 便于维护:改一处,全局生效
- 团队统一:大家都用
.btn-primary,风格自然统一
5.3.9 最佳实践:混合使用
实际开发中,Tailwind 和原生 CSS 可以混合使用,取长补短:
<template>
<div class="card">
<!-- 布局用 Tailwind,快速搞定 -->
<div class="flex items-center gap-4 mb-4">
<img :src="avatar" class="w-12 h-12 rounded-full" />
<div>
<h3 class="font-bold text-gray-800">{{ name }}</h3>
<p class="text-sm text-gray-500">{{ title }}</p>
</div>
</div>
<!-- 按钮用原生 CSS,方便复用 -->
<button class="btn btn-primary">关注</button>
</div>
</template>
<style scoped>
/* 可复用的组件样式用原生 CSS */
.card {
background: white;
border-radius: 1rem;
padding: 1.5rem;
box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1);
}
.btn {
padding: 0.5rem 1.5rem;
border-radius: 0.5rem;
font-weight: 500;
transition: all 0.2s;
}
.btn-primary {
background: #4f46e5;
color: white;
}
.btn-primary:hover {
background: #4338ca;
}
</style>什么时候用什么?
| 场景 | 推荐方案 | 理由 |
|---|---|---|
| 快速原型开发 | Tailwind | 不用切换文件,写得快 |
| 一次性布局 | Tailwind | 反正不会复用 |
| 可复用组件 | 原生 CSS | 定义一次,到处使用 |
| 需要动态样式 | 原生 CSS + CSS 变量 | 更容易通过 JS 控制 |
| 团队统一的 UI 组件 | 原生 CSS | 保证风格一致 |
简单说:布局用 Tailwind,组件用原生 CSS。
5.3.10 样式覆盖:谁写在后面谁赢
Tailwind 和原生 CSS 可以互相覆盖,规则很简单:后面的覆盖前面的。
<template>
<!-- Tailwind 的 text-red-500 会被 .special 覆盖 -->
<p class="text-red-500 special">这是什么颜色?</p>
</template>
<style scoped>
.special {
color: blue; /* 最终是蓝色! */
}
</style>覆盖规则
- 同优先级:后定义的覆盖先定义的
- scoped CSS:Vue 的 scoped 样式通常会覆盖 Tailwind(因为加了属性选择器,优先级更高)
- !important:可以强制覆盖,但尽量少用
这意味着你可以:
- 用 Tailwind 写基础样式
- 用原生 CSS 覆盖特殊情况
- 两种方式自由组合
5.4 创建个人主页
5.4.1 设计个人主页
一个好的个人主页通常包含:
┌─────────────────────────────────┐
│ 头像 + 名字 + 简介 │ ← Hero 区域
├─────────────────────────────────┤
│ 技能标签 │ ← 技能展示
├─────────────────────────────────┤
│ 最近文章 / 项目展示 │ ← 内容区域
├─────────────────────────────────┤
│ 社交链接 │ ← 联系方式
└─────────────────────────────────┘5.4.2 创建 Hero 组件
<!-- frontend/app/components/HeroSection.vue -->
<template>
<section class="text-center py-16">
<!-- 头像 -->
<div class="mb-6">
<img
:src="avatar"
:alt="name"
class="w-32 h-32 rounded-full mx-auto shadow-lg border-4 border-white"
/>
</div>
<!-- 名字和标题 -->
<h1 class="text-4xl font-bold text-gray-800 mb-2">
{{ name }}
</h1>
<p class="text-xl text-indigo-600 font-medium mb-4">
{{ title }}
</p>
<!-- 简介 -->
<p class="text-gray-600 max-w-2xl mx-auto leading-relaxed">
{{ description }}
</p>
<!-- 社交链接 -->
<div class="flex justify-center gap-4 mt-8">
<a
v-for="link in socialLinks"
:key="link.name"
:href="link.url"
target="_blank"
class="p-3 bg-white rounded-full shadow-md hover:shadow-lg hover:-translate-y-1 transition-all duration-300"
>
<span class="text-2xl">{{ link.icon }}</span>
</a>
</div>
</section>
</template>
<script setup>
defineProps({
name: {
type: String,
default: '你的名字'
},
title: {
type: String,
default: '全栈开发者'
},
avatar: {
type: String,
default: 'https://api.dicebear.com/7.x/avataaars/svg?seed=Felix'
},
description: {
type: String,
default: '热爱编程,热爱生活。正在学习全栈开发,希望能用技术改变世界。'
},
socialLinks: {
type: Array,
default: () => [
{ name: 'GitHub', icon: '🐙', url: 'https://github.com' },
{ name: 'Twitter', icon: '🐦', url: 'https://twitter.com' },
{ name: 'Email', icon: '📧', url: 'mailto:hello@example.com' },
]
}
})
</script>Props 是什么?
Props 是组件的"参数"。通过 Props,你可以让组件变得可配置:
<!-- 使用默认值 -->
<HeroSection />
<!-- 自定义值 -->
<HeroSection name="张三" title="前端工程师" />这样同一个组件就可以在不同地方显示不同的内容了。
5.4.3 创建技能展示组件
<!-- frontend/app/components/SkillsSection.vue -->
<template>
<section class="py-12">
<h2 class="text-2xl font-bold text-gray-800 text-center mb-8">
🛠️ 技能栈
</h2>
<div class="flex flex-wrap justify-center gap-3">
<span
v-for="skill in skills"
:key="skill.name"
class="px-4 py-2 rounded-full text-sm font-medium transition-all duration-300 hover:scale-105"
:class="skillClass(skill.category)"
>
{{ skill.icon }} {{ skill.name }}
</span>
</div>
</section>
</template>
<script setup>
defineProps({
skills: {
type: Array,
default: () => [
{ name: 'Vue.js', icon: '💚', category: 'frontend' },
{ name: 'Nuxt', icon: '💎', category: 'frontend' },
{ name: 'TypeScript', icon: '📘', category: 'frontend' },
{ name: 'Tailwind CSS', icon: '🎨', category: 'frontend' },
{ name: 'Python', icon: '🐍', category: 'backend' },
{ name: 'FastAPI', icon: '⚡', category: 'backend' },
{ name: 'PostgreSQL', icon: '🐘', category: 'backend' },
{ name: 'Docker', icon: '🐳', category: 'devops' },
{ name: 'Git', icon: '📦', category: 'devops' },
]
}
})
const skillClass = (category) => {
const classes = {
frontend: 'bg-green-100 text-green-700 hover:bg-green-200',
backend: 'bg-blue-100 text-blue-700 hover:bg-blue-200',
devops: 'bg-purple-100 text-purple-700 hover:bg-purple-200',
}
return classes[category] || 'bg-gray-100 text-gray-700'
}
</script>5.4.4 创建项目展示组件
<!-- frontend/app/components/ProjectsSection.vue -->
<template>
<section class="py-12">
<h2 class="text-2xl font-bold text-gray-800 text-center mb-8">
🚀 项目展示
</h2>
<div class="grid md:grid-cols-2 lg:grid-cols-3 gap-6">
<div
v-for="project in projects"
:key="project.name"
class="bg-white rounded-xl shadow-md overflow-hidden hover:shadow-xl transition-shadow duration-300"
>
<!-- 项目图片 -->
<div class="h-48 bg-gradient-to-br from-indigo-500 to-purple-600 flex items-center justify-center">
<span class="text-6xl">{{ project.icon }}</span>
</div>
<!-- 项目信息 -->
<div class="p-6">
<h3 class="text-lg font-bold text-gray-800 mb-2">
{{ project.name }}
</h3>
<p class="text-gray-600 text-sm mb-4">
{{ project.description }}
</p>
<!-- 技术标签 -->
<div class="flex flex-wrap gap-2 mb-4">
<span
v-for="tech in project.techs"
:key="tech"
class="px-2 py-1 bg-gray-100 text-gray-600 text-xs rounded"
>
{{ tech }}
</span>
</div>
<!-- 链接 -->
<div class="flex gap-4">
<a
v-if="project.github"
:href="project.github"
target="_blank"
class="text-gray-600 hover:text-gray-800 text-sm"
>
📦 源码
</a>
<a
v-if="project.demo"
:href="project.demo"
target="_blank"
class="text-indigo-600 hover:text-indigo-800 text-sm font-medium"
>
🔗 演示
</a>
</div>
</div>
</div>
</div>
</section>
</template>
<script setup>
defineProps({
projects: {
type: Array,
default: () => [
{
name: '个人博客',
icon: '📝',
description: '使用 Nuxt + FastAPI 构建的全栈博客系统,支持 Markdown 写作。',
techs: ['Nuxt', 'FastAPI', 'SQLite'],
github: 'https://github.com',
demo: 'https://example.com'
},
{
name: 'Todo 应用',
icon: '✅',
description: '一个简洁的待办事项应用,支持拖拽排序和数据持久化。',
techs: ['Vue 3', 'Pinia', 'LocalStorage'],
github: 'https://github.com',
demo: null
},
{
name: '天气查询',
icon: '🌤️',
description: '调用第三方 API 的天气查询应用,支持城市搜索和未来预报。',
techs: ['Vue 3', 'Axios', 'OpenWeather API'],
github: 'https://github.com',
demo: 'https://example.com'
},
]
}
})
</script>5.4.5 组装首页
现在把这些组件组装到首页:
<!-- frontend/app/pages/index.vue -->
<template>
<div>
<!-- Hero 区域 -->
<HeroSection
name="你的名字"
title="全栈开发学习者"
description="正在学习 Nuxt + FastAPI 全栈开发。热爱编程,热爱开源。希望通过这个博客记录自己的成长历程。"
/>
<!-- 分割线 -->
<hr class="border-gray-200 my-8" />
<!-- 技能展示 -->
<SkillsSection />
<!-- 分割线 -->
<hr class="border-gray-200 my-8" />
<!-- 项目展示 -->
<ProjectsSection />
<!-- 联系区域 -->
<section class="py-12 text-center">
<h2 class="text-2xl font-bold text-gray-800 mb-4">
📬 联系我
</h2>
<p class="text-gray-600 mb-6">
有任何问题或合作意向,欢迎随时联系我!
</p>
<a
href="mailto:hello@example.com"
class="inline-block px-8 py-3 bg-indigo-600 text-white rounded-lg font-medium hover:bg-indigo-700 transition"
>
发送邮件
</a>
</section>
</div>
</template>5.5 添加关于页面
让我们再创建一个"关于"页面,练习一下组件复用:
<!-- frontend/app/pages/about.vue -->
<template>
<div class="max-w-3xl mx-auto">
<h1 class="text-3xl font-bold text-gray-800 mb-8">
👋 关于我
</h1>
<div class="prose prose-lg">
<p class="text-gray-600 leading-relaxed mb-6">
你好!我是一名正在学习全栈开发的学生/开发者。
</p>
<h2 class="text-xl font-bold text-gray-800 mt-8 mb-4">
🎯 为什么学全栈?
</h2>
<p class="text-gray-600 leading-relaxed mb-6">
我相信掌握前后端技术能让我更好地理解整个 Web 应用的工作原理,
也能让我独立完成一个完整的项目。
</p>
<h2 class="text-xl font-bold text-gray-800 mt-8 mb-4">
📚 学习历程
</h2>
<ul class="list-disc list-inside text-gray-600 space-y-2 mb-6">
<li>学习了 HTML、CSS、JavaScript 基础</li>
<li>掌握了 Vue 3 和 Nuxt 框架</li>
<li>学习了 Python 和 FastAPI 后端开发</li>
<li>正在学习数据库和部署相关知识</li>
</ul>
<h2 class="text-xl font-bold text-gray-800 mt-8 mb-4">
🌟 未来计划
</h2>
<p class="text-gray-600 leading-relaxed">
继续完善这个博客系统,添加更多功能,同时也会把学习过程中的心得体会写成文章分享出来。
</p>
</div>
</div>
</template>5.6 小结
本章回顾
- ✅ 学习了经典的 Header/Main/Footer 三段式布局
- ✅ 理解了组件拆分的思想和好处
- ✅ 安装并快速上手了 Tailwind CSS
- ✅ 理解了 Tailwind CSS 的优缺点(类名冗长、复用困难、团队风格不统一)
- ✅ 掌握了 Tailwind 与原生 CSS 混合使用的最佳实践
- ✅ 创建了可复用的组件(HeroSection、SkillsSection、ProjectsSection)
- ✅ 组装了一个漂亮的个人主页
- ✅ 页面终于变好看了!
动手练习
试着扩展一下:
- 修改
HeroSection组件,添加你自己的信息 - 在
SkillsSection中添加你正在学习的技能 - 给 Header 添加一个移动端菜单按钮(响应式设计)
- 尝试调整 Tailwind 的颜色,换一套你喜欢的配色
记得把页面截图发给朋友看看!🎉
下一章预告
个人主页有了,但博客没有文章怎么行?下一章我们来实现文章列表功能,学习 Nuxt 路由和后端 API 设计!
准备好让你的博客有内容了吗?📝