Skip to content

Repository files navigation

react hooks+redux+immutable.js仿网易云音乐打造精美webApp

在线体验地址

从开发到拆解教程,前端万粉博主——神三元(掘金|知乎)全程亲自操刀,项目代码质量、可维护性均有保证。

系列拆解文章已经出炉,整理成了掘金小册,请点这里查看。如遇到问题,或者需要联系加群,请加微信: FESanyuan

移动端和PC端的chrome浏览器食用更佳 : )

打开方式:

  1. 将项目 clone 下来
$ git clone https://github.com/sanyuan0704/cloud-music.git
$ cd cloud-music
$ npm install
// 下载子模块
$ git submodule update --init --recursive
$ cd NeteaseCloudMusicApi
$ npm install $ cd ../ (注意: 一定要返回到上一层)

接下来,要记得把src/api/config.js中把baseUrl改成接口的地址。(一定要记得,不然报404!)

  1. 运行
$ npm run start

现在就在本地的3000端口访问了。如果要打包到线上,执行npm run build即可。

项目介绍:

说明:本项目参考网易云音乐安卓端app界面开发,基础UI绝大多数自己来构建,算是对自己的一个挑战,在这个过程也学到了不少设计经验。

功能介绍

1、推荐部分

首页推荐:

推荐歌单详情:

空中切入切出效果,另外还有随着滑动会产生和标题跑马灯效果。 在歌单中歌曲数量过多的情况下,做了分页处理,随着滚动不断进行上拉加载,防止大量DOM加载导致的页面卡顿。

2、歌手部分

歌手列表:

这里做了异步加载的处理,上拉到底进行新数据的获取,下拉则进行数据的重新加载。

歌手详情:

3、排行榜

榜单页:

榜单详情:

4、播放器

播放器内核:

播放列表:

会有移动端app一样的反弹效果。

5、搜索部分

项目部分模块分享

1、利用better-scroll打造超级好用的scroll基础组件

importReact,{forwardRef,useState,useEffect,useRef,useImperativeHandle}from"react"importPropTypesfrom"prop-types"importBScrollfrom"better-scroll"importstyledfrom'styled-components';import{debounce}from"../../api/utils";constScrollContainer=styled.div` width: 100%; height: 100%; overflow: hidden;`constScroll=forwardRef((props,ref)=>{const[bScroll,setBScroll]=useState();constscrollContaninerRef=useRef();const{ direction, click, refresh, pullUpLoading, pullDownLoading, bounceTop, bounceBottom }=props;const{ pullUp, pullDown, onScroll }=props;useEffect(()=>{if(bScroll)return;constscroll=newBScroll(scrollContaninerRef.current,{scrollX: direction==="horizental",scrollY: direction==="vertical",probeType: 3,click: click,bounce:{top: bounceTop,bottom: bounceBottom}});setBScroll(scroll);if(pullUp){scroll.on('scrollEnd',()=>{//判断是否滑动到了底部if(scroll.y<=scroll.maxScrollY+100){pullUp();}});}if(pullDown){scroll.on('touchEnd',(pos)=>{//判断用户的下拉动作if(pos.y>50){debounce(pullDown,0)();}});}if(onScroll){scroll.on('scroll',(scroll)=>{onScroll(scroll);})}if(refresh){scroll.refresh();}return()=>{scroll.off('scroll');setBScroll(null);}// eslint-disable-next-line},[]);useEffect(()=>{if(refresh&&bScroll){bScroll.refresh();}})useImperativeHandle(ref,()=>({refresh(){if(bScroll){bScroll.refresh();bScroll.scrollTo(0,0);}}}));constPullUpdisplayStyle=pullUpLoading ? {display: ""} : {display: "none"};constPullDowndisplayStyle=pullDownLoading ? {display: ""} : {display: "none"};return(<ScrollContainerref={scrollContaninerRef}>{props.children}{/* 滑到底部加载动画 */}<PullUpLoadingstyle={PullUpdisplayStyle}></PullUpLoading>{/* 顶部下拉刷新动画 */}<PullDownLoadingstyle={PullDowndisplayStyle}></PullDownLoading></ScrollContainer>);})Scroll.defaultProps={direction: "vertical",click: true,refresh: true,onScroll: null,pullUpLoading: false,pullDownLoading: false,pullUp: ()=>{},pullDown: ()=>{},bounceTop: true,bounceBottom: true};Scroll.propTypes={direction: PropTypes.oneOf(['vertical','horizental']),refresh: PropTypes.bool,onScroll: PropTypes.func,pullUp: PropTypes.func,pullDown: PropTypes.func,pullUpLoading: PropTypes.bool,pullDownLoading: PropTypes.bool,bounceTop: PropTypes.bool,//是否支持向上吸顶bounceBottom: PropTypes.bool//是否支持向上吸顶};exportdefaultReact.memo(Scroll);

2、富有动感的loading组件

importReactfrom'react';importstyled,{keyframes}from'styled-components';importstylefrom'../../assets/global-style'constdance=keyframes` 0%, 40%, 100%{ transform: scaleY(0.4); transform-origin: center 100%; } 20%{ transform: scaleY(1); }`constLoading=styled.div` height: 10px; width: 100%; margin: auto; text-align: center; font-size: 10px; >div{ display: inline-block; background-color: ${style["theme-color"]}; height: 100%; width: 1px; margin-right:2px; animation: ${dance} 1s infinite; } >div:nth-child(2) { animation-delay: -0.4s; } >div:nth-child(3) { animation-delay: -0.6s; } >div:nth-child(4) { animation-delay: -0.5s; } >div:nth-child(5) { animation-delay: -0.2s; } `functionLoadingV2(){return(<Loading><div></div><div></div><div></div><div></div><div></div><span>拼命加载中...</span></Loading>);}exportdefaultLoadingV2;

3、模块懒加载及代码分割(CodeSpliting)

react官方已经提供了相应的方案, 用react自带的lazy和Suspense即可完成。 操作如下:

importReact,{lazy,Suspense}from'react';constHomeComponent=lazy(()=>import("../application/Home/"));constHome=(props)=>{return(<Suspensefallback={null}><HomeComponent{...props}></HomeComponent></Suspense>)};
......
exportdefault[{path: "/",component: Home,routes: [{path: "/",exact: true,render: ()=>(<Redirectto={"/recommend"}/>)},{path: "/recommend/",extra: true,key: 'home',component: Recommend,routes:[{path: '/recommend/:id',component: Album,}]}......]},];

未来规划和展望

目前这个项目的核心已经完成,但是还是有很多扩展的余地。关于未来的规划,我是这么安排的:

  • 完成收藏、播放历史功能
  • 完成登录功能和评论模块
  • 实现MV模块
  • 同时撰写《手摸手,一起用React实现网易云音乐webApp》系列拆解文章
  • 未来更多功能待补充...

这个项目长期维护,希望大家踊跃提issue和pr,把这个项目打造得更加完美,帮助到更多的react开发者!

About

React 16.8打造精美音乐WebApp

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages