# 基于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![输入图片说明](https://images.gitee.com/uploads/images/2021/0726/233432_69b6ffc9_8386940.png "推荐1.png") | 2![输入图片说明](https://images.gitee.com/uploads/images/2021/0726/233442_3c9c2908_8386940.png "推荐2.png") | |---|---| ##### 1.2歌曲播放功能
- 顺序播放 - 单曲循环 - 随机播放 - 动态歌词 - 歌曲进度 - 拖拉进度 - 等等 | ![输入图片说明](https://images.gitee.com/uploads/images/2021/0726/234056_307a7f07_8386940.png "歌曲播放1.png") | ![输入图片说明](https://images.gitee.com/uploads/images/2021/0726/234105_57a84549_8386940.png "歌曲播放2.png") | |---|---| ##### 1.3歌词详情页面
包含歌词展示、歌词展开收起等功能 | 1![输入图片说明](https://images.gitee.com/uploads/images/2021/0727/105830_c5fbf024_8386940.png "歌详情1.png") | 2![输入图片说明](https://images.gitee.com/uploads/images/2021/0727/105847_99215063_8386940.png "歌详情2.png") | |---|---| ##### 1.4排行榜页面
包含排行榜数据展现、切换排行榜等功能 | 1![输入图片说明](https://images.gitee.com/uploads/images/2021/0727/110225_bf95268a_8386940.png "排行榜1.png") | 2![输入图片说明](https://images.gitee.com/uploads/images/2021/0727/110235_6f9ecb43_8386940.png "排行榜2.png") | |---|---| ##### 1.5歌单页面
包含分类选择、歌单卡片展示、分页等功能 | 1![输入图片说明](https://images.gitee.com/uploads/images/2021/0727/110533_2b391b04_8386940.png "歌单1.png") | 2![输入图片说明](https://images.gitee.com/uploads/images/2021/0727/110548_ea2fcf60_8386940.png "歌单2.png") | |---|---| ##### 1.6电台、歌手、新碟页面等等
由于页面较多涉及组件复用、数据展示等相同功能、展示,因此统一展示 | 1![输入图片说明](https://images.gitee.com/uploads/images/2021/0727/111325_5dfa98ed_8386940.png "电台1.png") | 2![输入图片说明](https://images.gitee.com/uploads/images/2021/0727/111334_02b709d3_8386940.png "电台2.png") | |---|---| | 1![输入图片说明](https://images.gitee.com/uploads/images/2021/0727/111354_51a671ac_8386940.png "歌手1.png") | 2![输入图片说明](https://images.gitee.com/uploads/images/2021/0727/111406_049d4efe_8386940.png "歌手2.png") | | 1![输入图片说明](https://images.gitee.com/uploads/images/2021/0727/111422_399474d1_8386940.png "新碟1.png") | 2![输入图片说明](https://images.gitee.com/uploads/images/2021/0727/111435_1c7efd2f_8386940.png "新碟2.png") | ##### 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 ```