Day 1 开发文档:项目初始化与基础架构搭建
一、项目初始化
1. 创建项目
首先,我们使用 Vite 创建一个基于 Vue 3 的项目:
# 创建项目
npm create vite@latest my-blog -- --template vue
# 这条命令会创建一个名为 my-blog 的新项目,使用 Vue 3 模板
# 进入项目目录
cd my-blog
# 安装项目依赖
npm install
2. 安装必要依赖
接下来,我们需要安装项目所需的核心依赖:
# 安装核心依赖
npm install vue-router@4 vuex@4 axios marked dompurify
# vue-router@4: Vue 3 的路由管理器,用于处理页面导航
# vuex@4: Vue 3 的状态管理库,用于管理全局状态
# axios: HTTP 请求库,用于与后端 API 通信
# marked: Markdown 解析器,用于解析文章内容
# dompurify: HTML 净化库,用于防止 XSS 攻击
# 安装开发依赖
npm install -D sass @types/node
# sass: CSS 预处理器,提供更强大的样式编写功能
# @types/node: Node.js 的 TypeScript 类型定义
3. 项目结构规划
创建以下目录结构,每个目录都有其特定用途:
blog-website/
├── src/
│ ├── components/ # 公共组件目录
│ │ ├── TheHeader.vue # 网站头部导航
│ │ ├── ScrollProgress.vue # 滚动进度条
│ │ ├── BlogCard.vue # 博客卡片
│ │ └── TheFooter.vue # 网站底部
│ ├── views/ # 页面组件目录
│ │ ├── HomeView.vue # 首页
│ │ └── BlogView.vue # 博客列表页
│ ├── router/ # 路由配置目录
│ │ └── index.js # 路由配置文件
│ ├── store/ # 状态管理目录
│ │ └── index.js # Vuex 配置文件
│ ├── api/ # API 接口目录
│ │ └── blog.js # 博客相关接口
│ └── assets/ # 静态资源目录
│ └── styles/ # 样式文件目录
│ ├── main.css # 主样式文件
│ └── responsive.css # 响应式样式
├── index.html # 入口 HTML 文件
└── package.json # 项目配置文件
二、基础组件开发
1. 响应式导航栏组件
[文件位置: src/components/TheHeader.vue]
TheHeader.vue 组件说明:
1. 功能:实现响应式导航栏
2. 主要特点:
- 自适应布局:在不同屏幕尺寸下自动调整显��方式
- 移动端菜单:在小屏幕设备上显示汉堡菜单按钮
- 动态交互:菜单展开/收起动画,滚动时自动隐藏/显示
3. 核心实现:
- 使用 Vue 3 组合式 API
- 响应式状态管理
- CSS 过渡动画
<template>
<header class="header" :class="{ 'header-hidden': isHeaderHidden }">
<div class="container">
<nav class="nav">
<!-- Logo 区域 -->
<router-link to="/" class="logo">
<h1>✨ My Blog ✨</h1>
</router-link>
<!-- 移动端菜单按钮 -->
<div class="menu-toggle" @click="toggleMenu">
<i class="fas fa-bars"></i>
</div>
<!-- 导航链接 -->
<ul class="nav-links" :class="{ active: isMenuOpen }">
<li v-for="item in menuItems" :key="item.path">
<router-link
:to="item.path"
@click="closeMenu"
active-class="active"
>
<i :class="item.icon"></i>
{{ item.name }}
</router-link>
</li>
</ul>
</nav>
</div>
</header>
</template>
<script setup>
import { ref } from 'vue'
// 控制菜单显示状态
const isMenuOpen = ref(false)
// 控制导航栏显示/隐藏
const isHeaderHidden = ref(false)
// 导航菜单项配置
const menuItems = [
{ path: '/', name: '首页', icon: 'fas fa-home' },
{ path: '/blog', name: '博客', icon: 'fas fa-cloud' }
]
// 切换菜单显示状态
const toggleMenu = () => {
isMenuOpen.value = !isMenuOpen.value
}
// 关闭菜单
const closeMenu = () => {
isMenuOpen.value = false
}
</script>
2. 滚动进度条组件
[文件位置: src/components/ScrollProgress.vue]
ScrollProgress.vue 组件说明:
1. 功能:显示页面阅读进度
2. 主要特点:
- 实时进度更新:随页面滚动实时计算和显示进度
- 平滑动画:使用 CSS 过渡实现流畅的进度更新
- 性能优化:使用节流函数优化滚动事件处理
3. 核心实现:
- 滚动事件监听
- 进度计算逻辑
- 组件生命周期管理
<template>
<div class="scroll-progress" :style="{ width: progress + '%' }"></div>
</template>
<script setup>
import { ref, onMounted, onUnmounted } from 'vue'
// 存储滚动进度
const progress = ref(0)
// 更新滚动进度
const updateProgress = () => {
// 计算页面总高度(减去视口高度)
const windowHeight = document.documentElement.scrollHeight - window.innerHeight
// 计算滚动百分比
const scrolled = (window.scrollY / windowHeight) * 100
progress.value = scrolled
}
// 组件挂载时添加滚动监听
onMounted(() => {
window.addEventListener('scroll', updateProgress)
})
// 组件卸载时移除监听,防止内存泄漏
onUnmounted(() => {
window.removeEventListener('scroll', updateProgress)
})
</script>
3. 博客卡片组件
[文件位置: src/components/BlogCard.vue]
BlogCard.vue 组件说明:
1. 功能:展示博客文章预览卡片
2. 主要特点:
- 响应式布局:适应不同屏幕尺寸
- 图片处理:懒加载和错误处理
- 内容格式化:日期和摘要的智能处理
3. 核心实现:
- 图片懒加载
- Markdown 解析
- XSS 防护
- 路由导航
<template>
<div class="blog-card" @click="handleClick">
<!-- 文章封面图片 -->
<div class="card-image">
<img
:src="post.image || '/images/placeholder.jpg'"
:alt="post.title"
@error="handleImageError"
>
</div>
<!-- 文章内容预览 -->
<div class="card-content">
<h3 class="card-title">{{ post.title }}</h3>
<p class="card-excerpt">{{ formatExcerpt(post.excerpt) }}</p>
<!-- 文章元信息 -->
<div class="card-meta">
<span class="date">
<i class="far fa-calendar-alt"></i>
{{ formatDate(post.date) }}
</span>
<span class="category">
<i class="fas fa-folder"></i>
{{ post.category }}
</span>
</div>
</div>
</div>
</template>
<script setup>
import { ref } from 'vue'
import { marked } from 'marked'
import DOMPurify from 'dompurify'
import { useRouter } from 'vue-router'
// 定义组件属性
const props = defineProps({
post: {
type: Object,
required: true
}
})
const router = useRouter()
// 处理卡片点击,跳转到文章详情
const handleClick = () => {
const id = props.post?.id
if (!id) return
router.push(`/blog/${id}`)
}
// 格式化文章摘要,去除 HTML 标签限制长度
const formatExcerpt = (excerpt) => {
if (!excerpt) return ''
const html = DOMPurify.sanitize(marked(excerpt))
const div = document.createElement('div')
div.innerHTML = html
let text = div.textContent || div.innerText || ''
return text.length > 200 ? text.slice(0, 200) + '...' : text
}
// 格式化日期显示
const formatDate = (date) => {
return new Date(date).toLocaleDateString('zh-CN')
}
// 处理图片加载失败
const handleImageError = (e) => {
e.target.src = '/images/placeholder.jpg'
}
</script>
三、路由配置
1. 基础路由设置
[文件位置: src/router/index.js]
配置页面路由和导航规则:
import { createRouter, createWebHistory } from 'vue-router'
import HomeView from '@/views/HomeView.vue'
import BlogView from '@/views/BlogView.vue'
const routes = [
{
path: '/',
name: 'home',
component: HomeView,
meta: {
title: '首页'
}
},
{
path: '/blog',
name: 'blog',
component: BlogView,
meta: {
title: '博客'
}
}
]
const router = createRouter({
history: createWebHistory(),
routes,
scrollBehavior(to, from, savedPosition) {
// 页面切换时滚动到顶部
return { top: 0 }
}
})
export default router
路由配置说明:
1. 功能:实现页面导航和路由控制
2. 主要特点:
- 历史模式:使用 HTML5 History API
- 路由懒加载:优化首屏加载时间
- 滚动行为:自动滚动到页面顶部
3. 核心实现:
- 路由注册
- 导航守卫
- 滚动控制
3. 懒加载优化
[文件位置: src/router/index.js, src/components/BlogCard.vue, src/App.vue]
为了提升性能,我们在以下几个方面实现了懒加载:
- 路由懒加载
// [文件位置: src/router/index.js]
const routes = [
{
path: '/',
name: 'home',
component: () => import('@/views/HomeView.vue') // 懒加载首页
},
{
path: '/blog',
name: 'blog',
component: () => import('@/views/BlogView.vue') // 懒加载博客页
}
]
- 图片懒加载
// [文件位置: src/components/BlogCard.vue]
<template>
<div class="blog-card">
<div class="card-image">
<img
:src="post.image || '/images/placeholder.jpg'"
:alt="post.title"
loading="lazy" // 使用浏览器原生懒加载
@error="handleImageError"
>
</div>
</div>
</template>
- 组件懒加载
// [文件位置: src/App.vue]
<script setup>
import { defineAsyncComponent } from 'vue'
// 懒加载非关键组件
const TheFooter = defineAsyncComponent(() =>
import('./components/TheFooter.vue')
)
// 带加载状态的懒加载组件
const BlogEditor = defineAsyncComponent({
loader: () => import('./components/BlogEditor.vue'),
loadingComponent: LoadingSpinner,
delay: 200,
timeout: 3000
})
</script>
- 懒加载效果
- 首屏加载时间优化:只加载必要的组件
- 图片加载优化:减少首屏请求数量
- 路由切换优化:按需加载页面组件
- 内存使用优化:减少初始化时的内存占用
四、状态管理
1. Vuex Store 配置
[文件位置: src/store/index.js]
配置全局状态管理:
import { createStore } from 'vuex'
import { blogApi } from '@/api/blog'
export default createStore({
// 状态定义
state: {
posts: [], // 文章列表
loading: false, // 加载状态
error: null // 错误信息
},
// 修改状态的方法
mutations: {
SET_POSTS(state, posts) {
state.posts = posts
},
SET_LOADING(state, loading) {
state.loading = loading
},
SET_ERROR(state, error) {
state.error = error
}
},
// 异步操作
actions: {
// 获取文章列表
async fetchPosts({ commit }) {
try {
commit('SET_LOADING', true)
const { data } = await blogApi.getPosts()
commit('SET_POSTS', data)
return data
} catch (err) {
commit('SET_ERROR', err.message)
throw err
} finally {
commit('SET_LOADING', false)
}
}
}
})
Vuex Store 配置说明:
1. 功能:全局状态管理
2. 主要特点:
- 集中管理数据
- 异步操作处理
- 状态追踪
3. 核心实现:
- 状态定义
- 同步修改
- 异步操作
五、样式系统
1. 全局主题变量
[文件位置: src/assets/styles/main.css]
定义全局样式变量,确保设计的一致性:
:root {
/* 颜色系统 - 定义网站配色方案 */
--color-primary: #3498db; /* 主要颜色 */
--color-secondary: #2ecc71; /* 次要颜色 */
--color-text: #2c3e50; /* 文本颜色 */
--color-background: #ffffff; /* 背景颜色 */
--color-border: #e0e0e0; /* 边框颜色 */
/* 字体系统 - 定义文字样式 */
--font-family: 'Inter', system-ui, sans-serif;
--font-size-base: 16px; /* 基础字号 */
--font-size-lg: 18px; /* 大号字体 */
--font-size-xl: 24px; /* 特大号字体 */
/* 间距系统 - 统一间距标准 */
--spacing-xs: 4px; /* 超小间距 */
--spacing-sm: 8px; /* 小间距 */
--spacing-md: 16px; /* 中等间距 */
--spacing-lg: 24px; /* 大间距 */
--spacing-xl: 32px; /* 特大间距 */
/* 圆角 - 统一圆角大小 */
--border-radius: 8px;
--border-radius-lg: 12px;
/* 阴影 - 统一阴影效果 */
--shadow-sm: 0 1px 3px rgba(0,0,0,0.12);
--shadow-md: 0 4px 6px rgba(0,0,0,0.1);
--shadow-lg: 0 10px 15px rgba(0,0,0,0.1);
}
2. 响应式布局
[文件位置: src/assets/styles/responsive.css]
实现移动端优先的响应式设计:
/* 移动端优先的响应式设计 */
.container {
width: 100%;
padding: 0 var(--spacing-md);
margin: 0 auto;
}
/* 平板设备断点 (>= 768px) */
@media (min-width: 768px) {
.container {
max-width: 720px; /* 限制容器最大宽度 */
}
.header__nav {
display: flex; /* 显示导航菜单 */
}
.header__toggle {
display: none; /* 隐藏菜单按钮 */
}
}
/* 桌面设备断点 (>= 1024px) */
@media (min-width: 1024px) {
.container {
max-width: 960px;
}
.posts-grid {
grid-template-columns: repeat(3, 1fr); /* 三列布局 */
}
}
/* 大屏设备断点 (>= 1280px) */
@media (min-width: 1280px) {
.container {
max-width: 1200px;
}
}
样式系统说明:
1. 功能:统一的设计系统
2. 主要特点:
- 主题变量:统一的颜色和尺寸
- 响应式设计:适配不同设备
- 组件样式:模块化的样式管理
3. 核心实现:
- CSS 变量系统
- 媒体查询
- 布局系统
六、第一天完成的功能
-
项目初始化
- 使用 Vite 创建 Vue 3 项目
- 安装必要的依赖包
- 规划项目目录结构
-
基础组件开发
- 响应式导航栏(TheHeader)
- 网站标题和 Logo
- 响应式菜单
- 移动端适配
- 滚动进度条(ScrollProgress)
- 实时显示阅读进度
- 平滑动画效果
- 博客卡片(BlogCard)
- 文章预览展示
- 图片加载优化
- 响应式布局
- 响应式导航栏(TheHeader)
-
路由配置
- 设置基础路由(首页、博客列表)
- 配置路由历史模式
- 添加滚动行为控制
-
状态管理
- 配置 Vuex store
- 实现文章数据管理
- 添加加载状态控制
-
样式系统
- 定义全局主题变量
- 实现响应式布局
- 设置统一的设计标准