# 基于React+Ant Design实现的仿网易云音乐官网网站
**Repository Path**: drmaple/ljmusic
## Basic Information
- **Project Name**: 基于React+Ant Design实现的仿网易云音乐官网网站
- **Description**: 后端基于开源的网易云音乐接口,前端基于React+Ant Design实现的web端应用
- **Primary Language**: JavaScript
- **License**: MIT
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 2
- **Created**: 2025-05-25
- **Last Updated**: 2025-05-25
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# 基于React+Ant Design实现的仿网易云音乐官网网站
### 1.项目简介
后端基于开源的 **[网易云音乐接口](https://neteasecloudmusicapi.js.org/#/)** ,前端基于React+Ant Design实现的web端应用
项目已经完成大部分页面展示与功能实现
项目预览地址: **[点我点我](http://106.52.112.127:7777/build)**
**项目仅作学习与交流**
##### 1.1推荐页面
包含轮播图、热门推荐、榜单等
| 1 | 2 |
|---|---|
##### 1.2歌曲播放功能
- 顺序播放
- 单曲循环
- 随机播放
- 动态歌词
- 歌曲进度
- 拖拉进度
- 等等
|  |  |
|---|---|
##### 1.3歌词详情页面
包含歌词展示、歌词展开收起等功能
| 1 | 2 |
|---|---|
##### 1.4排行榜页面
包含排行榜数据展现、切换排行榜等功能
| 1 | 2 |
|---|---|
##### 1.5歌单页面
包含分类选择、歌单卡片展示、分页等功能
| 1 | 2 |
|---|---|
##### 1.6电台、歌手、新碟页面等等
由于页面较多涉及组件复用、数据展示等相同功能、展示,因此统一展示
| 1 | 2 |
|---|---|
| 1 | 2 |
| 1 | 2 |
##### 1.7欠缺功能补充说明
页面内容展现较完善,但仍有一些功能没有实现,因此作出补充说明。搜索功能还没实现,登录功能还没实现,同时页面目前仅支持在 _发现音乐-推荐_ 里的榜单处点击播放另外歌曲,这些功能仍待完善,欢迎大家进行补充完善。
### 2.项目难点
##### 2.1技术栈
- React 页面布局、组件封装、页面逻辑等
- react-router 路由、路由跳转等
- redux 保存数据、数据共享等
- axios 发送Ajax请求等
- Ant Design 轮播图、分页实现等
- ImmutableJS 数据持久化,优化性能
- styled-components 第三方库,写CSS代码
##### 2.2项目难点
**复杂数据页面展示**
项目涉及比较多的页面布局和对请求到的数据进行处理展示,页面布局有些比较麻烦的地方和组件复用中的一些问题,这需要花费相当的时间进行样式布局和逻辑处理。
**歌曲切换与添加歌曲功能**
由于歌曲播放时允许设置三种模式:顺序播放、单曲循环、随机播放,当歌曲播放完时要进行播放判断从而进行不同处理,当手动添加新歌曲时,首先在歌曲播放列表中进行寻找,若没有则添加歌曲进入播放列表中,若歌曲播放列表中存在歌曲则切换歌曲播放的顺序,涉及比较多的逻辑处理和判断,这里给出部分代码,具体请参考完整项目所示
```
const changeMusic = (tag) => {
dispatch(changeCurrentIndexAndSongAction(tag))
}
const handleMusicEnded = () => {
if(sequence === 2){ //单曲循环
audioRef.current.current = 0
audioRef.current.play()
}else{
dispatch(changeCurrentIndexAndSongAction(1))
}
}
```
```
export const changeCurrentIndexAndSongAction = (tag) => {
return (dispatch, getState) => {
const playList = getState().getIn(["player", "playList"])
const sequence = getState().getIn(["player", "sequence"])
let currentSongIndex = getState().getIn(["player", "currentSongIndex"])
switch (sequence) {
case 1: // 随机播放
let randomIndex = Math.floor(Math.random() * playList.length)
while (randomIndex === currentSongIndex) {
randomIndex = Math.floor(Math.random() * playList.length)
}
currentSongIndex = randomIndex
break;
default: //循序播放
currentSongIndex = currentSongIndex + tag
if (currentSongIndex >= playList.length) {
currentSongIndex = 0
}
if (currentSongIndex < 0) {
currentSongIndex = playList.length - 1
}
}
const currentSong = playList[currentSongIndex]
dispatch(changeCurrentSongAction(currentSong))
dispatch(changeCurrentSongIndexAction(currentSongIndex))
dispatch(getLyricAction(currentSong.id))
}
}
```
**拖拉歌曲进度条时关联的动态变化**
由于是手动实现的歌曲播放控制面板,拖拉滑动条时歌曲播放进度(声音)、歌曲时间与歌词当然不会实现动态变化,歌曲播放进度(声音)的动态改变由audio元素的currentTime属性决定,歌曲时间的动态改变由滑动条回调时的value属性决定,歌词的动态变化由对歌词接口返回数据进行的逻辑判断决定,涉及比较多的逻辑处理和判断,这里给出部分代码,具体请参考完整项目所示
```
// 滑动条拖动时发生的回调
const slideChange = useCallback((value) => {
setIsChanging(true)
// 随着拖动,当前时间发生更改
const currentTime = value / 100 * duration / 1000
setCurrentTime(currentTime * 1000)
setProgess(value)
}, [duration])
// 滑动条结束拖动时发生的回调
const slideAfterChange = useCallback((value) => {
const currentTime = value / 100 * duration / 1000
audioRef.current.currentTime = currentTime
setCurrentTime(currentTime * 1000)
setIsChanging(false)
if(!isPlaying){
playMusic()
}
}, [duration, isPlaying, playMusic])
```
```
const timeUpdate = (e) => {
const currentTime = e.target.currentTime
if (!isChanging) {
setCurrentTime(currentTime * 1000)
setProgess(currentTime * 1000 / duration * 100)
}
// 获取当前歌词
let index = 0
for (let i=0; i currentTime * 1000){
index = i - 1
break
}
}
// console.log();
if (currentLyricIndex !== index) {
dispatch(changeCurrentLyricIndexAction(index))
let content = lyricList[index] && lyricList[index].content
message.open({
key: "lyric",
content: content,
duration: 0,
className: "lyric-class"
})
}
}
```
### 3.项目运行
clone项目:
```
git clone https://gitee.com/junjiangLi/ljmusic.git
```
安装项目依赖:
```
yarn
```
项目运行:
```
yarn start
```