2026年了,前端面试和毕业设计早就不看“会不会用Vue”,而是看“能不能拿一个完整项目讲清楚组件、状态、路由、接口联调、性能优化”。这次要聊的这个 Vue3 网易云音乐实战项目,正好就是打在这两个点上:技术栈是 Vue3 全家桶,业务是一个可演示、可截图的音乐播放器,还带源码和文档。
先一句话说清楚它能干什么:从零开始搭一个前后端分离的网易云音乐 Web 端项目,包括推荐歌单、排行榜、搜索、播放器、歌词展示、登录态处理这些高频功能。源码目录完整,文档覆盖从环境准备到部署上线的过程,既能当毕设交差,也能当面试项目讲。
这篇博客会按实际开发顺序,把项目从环境准备、接口服务启动、前端工程创建、核心功能实现,一直讲到调试、打包、面试怎么讲。源码可以下载,但建议先把我下面的流程走一遍,至少两小时能跑通。
1. 核心能力速览
| 能力项 | 说明 |
|---|---|
| 项目类型 | 前后端分离的单页应用(SPA)实战项目 |
| 前端技术栈 | Vue3 + Vite + Pinia + Vue Router + Axios |
| 后端数据源 | 网易云音乐公开接口服务,本地启动,通过 HTTP 请求获取音乐数据 |
| 主要功能 | 推荐页、排行榜、歌单详情、搜索、播放器、歌词展示、登录态保存 |
| 播放能力 | 通过音频链接播放,支持播放/暂停/上一首/下一首/进度条切换 |
| 登录方式 | 二维码登录或邮箱登录,登录后获取 cookie 并保存到本地 |
| 启动方式 | 先启动接口服务,再启动前端开发服务器 |
| 是否支持 API | 支持,项目内封装统一请求模块,可二次开发 |
| 是否支持批量任务 | 不涉及批量任务,但支持列表数据按分页加载 |
| 适合人群 | Vue3 初学者、前端应届生、毕业设计学生、需要面试项目经验的开发者 |
从资料看,这个项目的重点不是把界面做得像网易云,而是让你跑通一条完整链路:前端页面 -> 请求封装 -> 接口服务 -> 音乐数据 -> 播放器渲染。这条链路就是你面试时能讲清楚的核心。
2. 适用场景与使用边界
这个项目适合三类人。
第一类是准备毕业设计的同学。音乐播放器需求明确、功能边界清楚、可截图可录屏,答辩时展示效果好,而且“接口对接”本身就是加分项。
第二类是准备前端面试的人。Vue3 面试题里常问的ref、reactive、computed、watch、Pinia、Vue Router、Axios拦截器,在这套源码里都能找到对应实现。你不需要背题,直接讲“我项目里在哪用了、为什么这么用”就可以。
第三类是刚学完 Vue3 基础、想找一个完整项目练手的人。比起重复写 TodoList,这种带真实接口、有异步数据、有播放器状态管理的项目,能帮你把零散知识点串起来。
使用边界也要说清楚。
接口服务本质是逆向网易云音乐网页版接口,只适合学习、个人测试和毕设演示,不能用于商用,也不能直接部署上线对外提供服务。登录功能涉及用户 cookie,本地开发时不要把自己的账号 cookie 提交到公开仓库。如果需要公开源码,建议把登录接口和 cookie 相关逻辑做脱敏处理,或者只保留游客模式。
另外,项目里的音乐资源版权归网易云音乐官方所有。演示时使用免费歌曲或试听片段没有问题,但不要把这些音频资源打包进项目分发,更不要用于任何商业场景。
一句话总结:本地跑通、学习原理、毕业展示,没问题;商用或大量分发,不行。
3. 环境准备与前置条件
从标题看,项目是“从零开始手把手教学”,所以环境准备部分必须干净。下面给出一套通用检查清单,具体版本号以你本机安装结果为准。
3.1 安装 Node.js
Vue3 和 Vite 都运行在 Node.js 环境上。建议安装 Node.js 的 LTS 版本,通常 18 或 20 以上即可。安装完成后,在终端执行:
node -v npm -v如果两个命令都能输出版本号,说明 Node.js 环境正常。
如果你喜欢用 pnpm 或 yarn,也可以装一个:
npm install -g pnpm3.2 准备接口服务
网易云音乐 Vue3 实战项目通常依赖一个独立的接口服务来提供音乐数据,常见方案是开源的 NeteaseCloudMusicApi 项目。你需要把它单独下载到本地某个目录,然后启动。
git clone https://github.com/Binaryify/NeteaseCloudMusicApi.git cd NeteaseCloudMusicApi npm install npm start默认情况下,接口服务会运行在http://localhost:3000。启动成功后,浏览器直接访问这个地址,能看到接口文档首页。
这里有一个常见的坑:如果你下载的代码版本较新,可能需要更高版本的 Node.js。如果npm install报错,优先检查 Node.js 版本,而不是反复重装依赖。
3.3 准备前端项目源码
假设你已经下载了本项目的源码压缩包或克隆到了douyin-music之类的前端目录。目录结构可能长这样:
douyin-music ├── public ├── src │ ├── api │ ├── assets │ ├── components │ ├── router │ ├── stores │ ├── views │ ├── App.vue │ └── main.js ├── .env.development ├── package.json └── README.mdsrc/api是接口请求封装目录,src/stores是 Pinia 状态管理目录,src/views是页面视图目录。先记住这几个目录的位置,后面调试和面试讲项目都会用到。
3.4 常见问题:端口被占用
接口服务默认占用 3000 端口,前端开发服务器默认占用 5173 端口。如果这两个端口被其他程序占用,启动时会报错。排查方式:
lsof -i :3000 lsof -i :5173如果端口占用,要么关掉对应进程,要么在配置里改端口。后面第 8 节会详细讲。
4. 安装部署与启动方式
环境准备好之后,按照下面的顺序启动。先启动接口服务,再启动前端工程,不要倒过来。
4.1 启动网易云音乐接口服务
打开终端,进入接口服务目录:
cd NeteaseCloudMusicApi npm start启动日志里会显示端口号,通常是3000。验证方式:打开浏览器输入http://localhost:3000,能看到接口文档地址或者返回 JSON,说明服务正常。
为了保险,可以先请求一个最简单的接口:
curl http://localhost:3000/personalized?limit=3如果返回 JSON 数据,里面包含推荐歌单列表,说明接口通了。
4.2 安装前端项目依赖
切换到前端项目目录:
cd douyin-music npm install安装过程可能耗时几分钟。如果某些依赖安装失败,可以尝试:
npm install --registry=https://registry.npmmirror.com这是国内镜像源,下载速度更快,也能解决部分网络问题。
4.3 配置接口地址环境变量
很多实战项目会把接口地址放到.env.development文件里,这样写代码的时候不用把域名写死。
VITE_BASE_API=http://localhost:3000如果接口服务地址不同,改这个文件就行。改完后需要重启前端开发服务器才会生效。
4.4 启动前端开发服务器
npm run dev启动成功后,终端会输出本地访问地址,通常是http://localhost:5173。
在浏览器打开这个地址,如果能看到页面,并且首页能加载出推荐歌单或排行榜数据,说明前后端已经打通。
4.5 打包构建
毕设或面试前需要部署演示,执行:
npm run build构建产物会输出到dist目录。把dist目录放到任意静态服务器上即可访问。Vite 默认用绝对路径,如果你要部署到子路径,需要改base配置,这里先不展开。
5. 核心功能模块与测试验证
项目跑通之后,逐项验证核心功能。下面按照“页面 -> 测试步骤 -> 预期结果”的方式列出,每项都能截图和录屏。
5.1 首页推荐
打开首页,通常包含轮播图和推荐歌单列表。
测试步骤:
- 确认首页能看到轮播图,图片能正常加载。
- 下拉页面,推荐歌单列表能显示专辑封面和名称。
- 点击一个推荐歌单,跳转到歌单详情页。
预期结果:
- 数据来自接口服务,不是写死在前端的。
- 歌单封面图加载速度正常,没有大量裂图。
如果首页空白,先打开浏览器开发者工具 Network 面板,看接口请求是否返回 200。如果请求 404,检查接口地址配置。
5.2 排行榜
进入排行榜页面,至少验证三个点:
- 榜单分类是否显示完整。
- 点击榜单后,歌曲列表是否加载。
- 歌曲列表是否有评分或播放次数等字段。
排行榜接口的特点是返回数据大,容易因为渲染性能问题造成页面卡顿。如果数据量很大,可以观察列表滚动是否流畅,这对应着后面的性能优化。
5.3 搜索
搜索是前端面试里高频考点,很多项目会把搜索框、防抖、请求时序控制放在一起考察。
测试步骤:
- 在顶部搜索框输入关键词,比如“周杰伦”或“海阔天空”。
- 查看搜索结果是否包含“单曲”“歌手”“专辑”“歌单”等多个分类。
- 快速多次输入不同关键词,观察页面是否出现旧数据覆盖新数据的问题。
预期结果:
- 搜索结果按分类展示。
- 最后一次输入的关键词结果,不会被前一次搜索结果覆盖。
这个测试点很重要,背后对应的是请求竞态处理,面试时可以重点讲。
5.4 播放器
播放器是这个项目最大的亮点,也是最容易出问题的模块。
测试步骤:
- 点击任意一首歌曲的播放按钮。
- 观察底部播放器是否出现歌曲名、歌手名、专辑封面。
- 点击播放/暂停,确认按钮状态切换正常。
- 拖动进度条,确认音频跳转位置正确。
- 点击“下一首”,确认播放列表按顺序切换。
预期结果:
- 歌曲可以正常播放,没有跨域或 403 错误。
- 播放器状态和页面状态联动,比如当前播放歌曲的列表项有特殊高亮。
这里最常见的报错是音频 URL 403。原因是部分音乐链接需要携带正确的 Referer 头,如果接口服务处理不好,音频会拒绝播放。遇到这个问题,优先检查接口服务和前端页面的域名是否一致,或者查看接口文档里关于音频 URL 的说明。
5.5 歌词展示
歌词功能能体现一个项目做没做完整。
测试步骤:
- 播放一首歌词接口能返回的歌曲。
- 播放时,页面是否展示歌词。
- 随着播放进度变化,歌词是否逐行高亮。
预期结果:
- 歌词能随播放进度滚动。
- 当前歌词行高亮显示。
如果歌词一直为空,先确认歌曲本身是否提供歌词接口,再检查接口返回的数据结构,看看是lrc字段还是lyric字段。
5.6 登录态
登录功能这里要特别强调:只建议用于学习测试,不要用真实高频账号。
测试步骤:
- 点击登录按钮,选择二维码或邮箱登录。
- 登录成功后,页面右上角显示用户头像或昵称。
- 刷新页面,确认登录状态是否保留。
预期结果:
- 登录后能获取用户相关信息。
- 刷新后通过 cookie 恢复登录状态。
如果刷新后登录态丢失,重点检查登录接口返回的 cookie 是否被正确保存,以及 Axios 请求配置是否设置了withCredentials。
5.7 收藏与歌单
如果项目包含收藏功能,测试关注:
- 点击收藏按钮,按钮状态是否变化。
- 重新进入页面,收藏状态是否保持。
收藏功能涉及用户维度的数据,通常依赖登录态。未登录状态下点击收藏,预期应跳转登录或给出提示。
6. 接口层设计与请求封装
接口层是前后端分离项目里最重要的工程化设计之一。面试时,这一节讲清楚了,比你背十道 Vue3 面试题都有用。
6.1 统一 Axios 请求封装
项目里一般会有一个src/api/request.js或src/utils/request.js,核心作用是把 Axios 实例、拦截器、错误处理统一起来。
import axios from 'axios' const request = axios.create({ baseURL: import.meta.env.VITE_BASE_API, timeout: 10000 }) request.interceptors.request.use(config => { const cookie = localStorage.getItem('music_cookie') if (cookie) { config.headers.Cookie = cookie } return config }) request.interceptors.response.use( response => { const res = response.data if (res.code !== 200) { return Promise.reject(new Error(res.message || '请求失败')) } return res }, error => { return Promise.reject(error) } ) export default request这段代码体现了三个面试点:baseURL从环境变量读取、请求拦截器注入 cookie、响应拦截器统一处理错误码。
6.2 接口模块拆分
页面里不要直接写request.get('/personalized'),而是把接口按业务模块拆分到src/api目录。
import request from '@/utils/request' export function getPersonalized() { return request({ url: '/personalized', method: 'get' }) } export function getSongUrl(id) { return request({ url: '/song/url', method: 'get', params: { id } }) } export function getLyric(id) { return request({ url: '/lyric', method: 'get', params: { id } }) }这样做的收益是:接口地址集中管理,修改接口路径不用全局搜索;组件的代码更干净;接口模块可以单独做单元测试。
6.3 搜索接口的竞态处理
搜索框快速输入时,先发的请求可能后返回,导致旧结果覆盖新结果。常见解决方案是保存一个请求序号,或者使用 AbortController 取消上一次请求。
import { ref } from 'vue' const searchLoading = ref(false) let reqId = 0 async function handleSearch(keyword) { const currentId = ++reqId searchLoading.value = true const res = await searchMusic(keyword) if (currentId === reqId) { searchList.value = res.result.songs searchLoading.value = false } }这段逻辑在面试里很加分,因为它说明你不只是会调接口,还理解异步竞态。
7. 性能优化与资源占用观察
7.1 路由懒加载
Vue3 实战项目工程化好不好,第一个看路由配置。路由懒加载能减少首屏加载时间。
const router = createRouter({ history: createWebHistory(), routes: [ { path: '/', name: 'Home', component: () => import('@/views/Home.vue') }, { path: '/playlist/:id', name: 'PlaylistDetail', component: () => import('@/views/PlaylistDetail.vue') } ] })7.2 图片懒加载
歌单封面和排行榜图片数量多,全量加载会拖慢首屏。可以在项目里安装vue-lazyload或使用原生loading="lazy"。
<img v-lazy="playlist.coverImgUrl" alt="封面" />7.3 组件拆分
一个页面几十行是正常的,但一个页面几百行就该拆组件了。以播放器为例,合理的拆分方式:
components ├── Player │ ├── PlayerBar.vue │ ├── PlayerLyric.vue │ └── PlayList.vue播放器作为全局组件挂在App.vue里,用 Pinia 管理播放状态,页面只负责触发播放。
7.4 资源占用观察
前端项目不像 AI 模型那样有显存占用,但没有明确材料依据,不要编造。可以用浏览器开发者工具的 Performance 面板和 Vue Devtools 观察:
- 打开浏览器 DevTools,进入 Network 面板,看首屏请求数量和资源体积。
- 切到 Performance 面板,点击录制,然后操作页面,观察主线程占用和长任务。
- 如果列表滚动卡顿,检查是不是渲染了大量 DOM 节点。
优化方向是明确的:减少首屏无关请求、路由懒加载、图片懒加载、列表虚拟滚动。
8. 常见问题与排查方法
| 问题现象 | 可能原因 | 排查方式 | 解决方案 |
|---|---|---|---|
| 首页数据加载不出来 | 接口服务未启动或地址配置错误 | 访问 http://localhost:3000 看是否返回 JSON | 启动接口服务,检查.env.development里的VITE_BASE_API |
| 接口返回 404 | 接口路径写错或某个接口需要额外参数 | 对比接口文档,Network 面板查看请求 URL | 修正请求路径或补全参数 |
| 音频无法播放,控制台报 403 | 音频 URL 缺少 Referer 头或已过期 | Network 面板查看音频请求响应 | 确认接口服务版本;前端可尝试携带合理 Referer |
| 播放器切歌后歌词不同步 | 歌词接口返回的是原始歌词,没有按时间解析 | console 打印歌词数据结构 | 查看歌词数据字段,如果返回的是字符串,需要做 lrc 格式解析 |
| 登录后刷新掉登录态 | cookie 未保存或请求未携带 cookie | 查看 localStorage 中是否保存 cookie,请求头是否带 Cookie | 设置withCredentials,并在请求拦截器注入 cookie |
| 点击播放后没有声音 | 播放器 audio 元素没有正确绑定 src | Vue Devtools 查看当前播放歌曲 URL | 检查getSongUrl接口返回的 URL 字段名 |
| npm install 报错 | Node 版本过低或依赖冲突 | 终端查看完整报错日志 | 升级 Node.js,换镜像源安装 |
| 端口被占用 | 服务启动时提示 address already in use | lsof -i :3000查看占用进程 | 换端口启动或关闭占用进程 |
这 8 个问题是这个类型项目的主要故障点,排查时一定按顺序来:先看接口服务通不通,再看前端请求到不到位,最后看渲染层。
9. 最佳实践与改造建议
9.1 毕设答辩演示顺序
不要一上来就点开播放器。建议按这个顺序演示:
- 先打开接口服务终端,展示接口请求日志。
- 再打开前端页面,展示推荐页。
- 从点击歌单,到进入详情,再到点击播放。
- 最后展示搜索功能和登录态。
这套顺序体现了“前后端分离”这个关键词,比直接播歌更有说服力。
9.2 目录结构管理
模型文件、源码、文档、接口服务分开目录。比如:
project ├── doc # 项目文档 ├── douyin-music # 前端源码 ├── NeteaseCloudMusicApi # 接口服务 └── README.md这样无论是自己后续开发,还是交给指导老师审查,都不会乱。
9.3 面试怎么讲
面试官如果问“这个项目你负责哪些模块”,不要回答“我都写了”。建议选 2 到 3 个模块讲深一点:
- 播放器模块:讲 Pinia 状态设计,播放列表如何管理,切歌逻辑如何实现。
- 搜索模块:讲防抖、竞态处理、接口拆分。
- 接口层设计:讲 Axios 封装、环境变量配置、cookie 处理。
每个模块都能落到具体代码位置,比背题效果强得多。
9.4 可扩展的方向
跑通项目之后,可以尝试加这些功能:
- 收藏歌曲:涉及登录态和用户维度接口。
- 历史播放记录:用 localStorage 持久化,前端面试常问。
- 评论模块:涉及时间格式化、分页加载和按热度排序。
- 响应式适配:移动端下播放器和歌单展示如何调整。
每加一个功能,项目简历上都多一个可展开的点。
10. 总结与下一步
这个 Vue3 网易云音乐实战项目最值得尝试的点有两处,一个是前端工程链路完整,另一个是播放器状态管理有真实业务复杂度,这两个点足够撑起一次毕业答辩或一轮前端技术面试。
先说建议优先验证的功能:首页推荐数据和播放器播放。这两个打通了,项目后续基本能顺畅跑起来。
再说最容易踩的坑:接口服务和前端项目的启动顺序,以及音频 URL 403。启动顺序错了,页面一片空白;音频 403 了,播放器看着是好的但就是没声音。这两个问题排查一次就记住了。
接下来可以做什么?第一,把项目源码完整读一遍,特别是src/api、src/stores、src/components/Player这三个目录。第二,挑一个自己薄弱的功能模块,比如搜索或歌词解析,重新写一遍。第三,把日志、错误处理、加载状态补齐,让项目从“能跑”提升为“像工业级项目”。
如果你打算把它作为面试项目,建议在 README 里写清楚技术栈、启动方式和核心模块说明,面试官第一眼就能看到你的项目价值。收藏这篇文章,部署的时候照着操作,基本能一次跑通。