Giter Club home page Giter Club logo

react-cloud-music's Introduction

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基础组件

import React, { forwardRef, useState,useEffect, useRef, useImperativeHandle } from "react"
import PropTypes from "prop-types"
import BScroll from "better-scroll"
import styled from 'styled-components';
import { debounce } from "../../api/utils";

const ScrollContainer = styled.div`
  width: 100%;
  height: 100%;
  overflow: hidden;
`

const Scroll = forwardRef((props, ref) => {
  const [bScroll, setBScroll] = useState();

  const scrollContaninerRef = useRef();

  const { direction, click, refresh, pullUpLoading, pullDownLoading, bounceTop, bounceBottom } = props;

  const { pullUp, pullDown, onScroll } = props;

  useEffect(() => {
    if(bScroll) return;
    const scroll = new BScroll(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);
      }
    }
  }));

  const PullUpdisplayStyle = pullUpLoading ? { display: "" } : { display: "none" };
  const PullDowndisplayStyle = pullDownLoading ? { display: "" } : { display: "none" };
  return (
    <ScrollContainer ref={scrollContaninerRef}>
      {props.children}
      {/* 滑到底部加载动画 */}
      <PullUpLoading style={ PullUpdisplayStyle }></PullUpLoading>
      {/* 顶部下拉刷新动画 */}
      <PullDownLoading style={ 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//是否支持向上吸顶
};

export default React.memo(Scroll);

2、富有动感的loading组件

import React from 'react';
import styled, {keyframes} from 'styled-components';
import style from '../../assets/global-style'

const dance = keyframes`
    0%, 40%, 100%{
      transform: scaleY(0.4);
      transform-origin: center 100%;
    }
    20%{
      transform: scaleY(1);
    }
`
const Loading = 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;
    } 
`

function LoadingV2() {
  return (
    <Loading>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <span>拼命加载中...</span>
    </Loading>
  );
}
 
export default LoadingV2;

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

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

import React, {lazy, Suspense} from 'react';
const HomeComponent = lazy(() => import("../application/Home/"));
const Home = (props) => {
  return (
    <Suspense fallback={null}>
      <HomeComponent {...props}></HomeComponent>
    </Suspense>
  )
};
......
export default [
  {
    path: "/",
    component: Home,
    routes: [
      {
        path: "/",
        exact: true,
        render:  ()=> (
          <Redirect to={"/recommend"}/>
        )
      },
      {
        path: "/recommend/",
        extra: true,
        key: 'home',
        component: Recommend,
        routes:[{
          path: '/recommend/:id',
          component: Album,
        }]
      }
      ......
    ]
  },

];

未来规划和展望

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

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

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

react-cloud-music's People

Contributors

baojiawei avatar ntnyq avatar sanyuan0704 avatar thoughtzer avatar uglyspoon avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

react-cloud-music's Issues

请问routes的属性extra是什么作用?

我看了下react-router 和react-rouer-config的文档,都没找到这属性。
全文搜索,也没在其他地方出现。

{
        path: "/recommend/",
        extra: true,
        key: 'home',
        component: Recommend,
        routes:[{
          path: '/recommend/:id',
          component: Album,
        }]
      },

此项目的小程序版本

是否可以使用taro这种工具,让此项目也能跑在微信小程序中,更加方便大家的使用。

使用的用户越多,对项目的发展越好吧

所有接口报502错误

貌似是接口的问题,返回信息:
{ code: 502,
msg: 'Error: read ECONNRESET\n at TLSWrap.onStreamRead (internal/stream_base_commons.js:111:27)' }
}
TLS相关错误,难道是网易云那边改成https协议了?

test

有的时候搜索框辉闪烁

运行npm install 报错

运行报错,发现第一次npm install后node_modules里面的依赖库只有一个.staging文件

! Unexpected end of JSON input while parsing near '...rElqHOGVJ3DRDcc+S+H Sj'
另一个npm install 正常,本地的node是v10

.md文件中的图片是如何处理的

大佬,我之前是将.md文件中图片放到一个仓库,然后通过在我的另外一个仓库的.md文件中使用图片的下载链接访问的,但是编辑完提交之后就是现实不出来,我查了一下,要在host文件中加一段好像是ip的映射才能正常显示,但是我这个仓库是要给人家看的啊,我不可能去让人家为了看我的仓库还要去改自己电脑的host文件这么麻烦吧,想必是你你也会难得看了吧哈哈哈哈。所以请大佬赐教,如何正确的在.md文件中放图片才可以像这个仓库中一样随时都能正常显示。多谢了!

移动端页面缩放后无法放大缩小

发现了几个缩放问题:

1、点击“搜索”,input标签没有获取到焦点,点击输入框后放大页面后,页面无法再缩小

IMG_4700

2、返回主页面后依旧无法缩小

IMG_4716

3、“排行榜”点击榜单,头部被遮挡

IMG_4698

歌词不能正常滚动

Player 组件中,handleLyric 方法的判断条件有些问题,currentLineNum.current 初始值为 0,是一个 falsy 值,会导致这个判断一直为 true

第三章缺少依赖

scroll/index.js里面使用了prop-types,但是实际package.json里面没有add。

子模块下载不下来啊,老哥

E:\workspace\cloud-music (master -> origin)
$ git submodule update --init --recursive
Cloning into 'E:/workspace/cloud-music/NeteaseCloudMusicApi'...

一直这个状态

优化小建议

排行榜页面刚进去的时候可以隐藏掉官方榜和全球榜两个title 不然挤在一起有点奇怪

Player组件中的歌词问题

第一个问题:对歌词的解析。好像只解析了“02:10.158”这种格式的,像"02:10:158"这种格式的没有解析,所以有些原本有歌词的歌曲显示的是纯音乐;
第二个问题:歌词内容显示错乱(无意间发现的):当前播放歌曲显示的歌词为纯音乐,点击下一首(有歌词的),然后再点击上一首(回到纯音乐),这时候本来是显示纯音乐却显示了刚刚那首歌的歌词;
第三个问题:CD和歌词组件切换,如果暂停歌曲,好像切换不了(或则反应很慢);
第四个问题:搜索组件有一个小小的bug:点击清除按钮,input框的值没有清掉。

搜索框bug

搜索框输入、删除输入的时候,有时会出现乱跳,不停请求的情况

看了下大佬的项目,想请教一下项目的适配

如题,想请教下大佬适配的问题,百分比布局+flex布局+媒体查询,然后字体部分\padding\margin都是用的固定宽高,老哥没有进行进行webpack方面的适配配置吗?还有大佬,现在的webAPP的适配是怎么做的,大佬帮忙指点一下吧

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.