React模仿网易云音乐实现一个音乐项目详解流程

目录
  • 一、项目功能说明
  • 二、最终效果
  • 三、文件目录结构说明
  • 四、项目技术栈
  • 五、核心技术
  • 六、遇到的问题
  • 七、github链接

一、项目功能说明

  1. 暂停、播放歌曲
  2. 切换上一首、下一首歌曲
  3. 拖动进度条改变播放进度
  4. 随机播放、循环播放、单曲循环
  5. 实时展示歌词
  6. 切换不同分类的歌单、歌手、电台
  7. 实现推荐、排行榜、歌单、主播电台、歌手、新碟上架板块的展示

二、最终效果

首页:

排行榜:

歌单:

主播电台:

歌手:

新碟上架:

三、文件目录结构说明

  • assets:存放共用的css、font图标、image
  • common:存放共用的资源,如数据、常量
  • components:存放多个页面共享的组件
  • pages:划分各个页面
  • router:路由配置
  • services:网络请求
  • store:合并所有reducer
  • utils:一些js的工具

四、项目技术栈

  • React 作为前端框架
  • Ant Design 作为前端UI框架
  • Redux 进行状态管理
  • Axios 进行网络请求
  • 通过调用网易云的API来获取数据
  • 使用 react-router-dom 的 Route, Switch 管理路由
  • 使用普通css 及 styled-component 编写 CSS

五、核心技术

  • 配置项目别名:@craco/craco

craco还可以进行wepback 进行自定义配置、antd 组件按需加载、支持 less等操作。不选择 npm run eject 是因为eject是不可逆操作。

安装:npm i @craco/craco

在package.json中的配置:

"scripts": {
    "start": "craco start",
    "build": "craco build",
    "test": "craco test",
    "eject": "react-scripts eject"
  },

根目录下创建 craco.config.js

重启项目

  • 使用reset.css进行 css 重置

通过 import './assets/css/reset.css'引入。但 reset.css 存在一个很大的问题是它将所有的浏览器的默认样式清除,从而达到所有浏览器样式的统一的目的,但这么操作会导致浏览器原本的默认样式失去意义。比起 reset.css 我更倾向于使用 normalize.css 来统一样式, normalize.css 是在尽量保留浏览器的默认样式的基础上,不进行太多的重置,这样保留了有价值的默认值,它还可以模块化引入、修复了浏览器的一些 bug、没有复杂的继承链。

  • 使用CSS Sprites 精灵图

本次项目很多地方使用了CSS Sprites 精灵图技术,可以有效减少图片的请求次数,优化性能。

  • 使用 memo 包裹函数式组件,减少渲染次数

React.memo是一个高阶函数,与类组件里面的 PureComponent类似,它传递一个组件进去,返回一个可以记忆的组件,在 props 不变的情况下,这个被包裹的组件是不会重新渲染的,这样就减少了 render 的渲染次数,从而提高了性能。

export default memo(function App() {
  return (
    <div className="App">
    </div>
   )
 })
  • AppHeader以及AppFooter的布局实现

使用 styled-components 编写css样式,通过 import styled from 'styled-components'引入css 文件

导航栏使用flex布局

导航栏前三项采用 路由跳转、后三项是链接跳转

搜索栏使用了 antd 的样式,通过 import { Input } from 'antd'引入

搜索图标使用了antd 的图标库,通过import { SearchOutlined } from '@ant-design/icons'引入

  • 推荐页轮播图采用 antd 的 Carousel走马灯组件完成

背景的模糊效果使用高斯模糊,通过改变请求的url ?imageView&blur=40x20 实现,css可以用filter: blur(20px);实现

  • 自定义公共组件,实现组件的复用

以下内容都被抽取到 components目录中。

  • 对于图片及播放次数也做了格式化处理

图片的处理:在 utils 目录的 format-utils 下编写 getSizeImage 函数,根据输入的参数来决定图片的大小

对数字的处理:在 utils 目录的 format-utils 下编写 getCount 函数,格式化歌曲播放数量,让用户可以更直观的知道播放次数

  • 播放音乐板块

播放/暂停音乐:采用了 html5 的 audio 标签实现,通过点击播放/暂停按钮实现歌曲的播放或暂停,通过isPlaying来获取当前播放状态,从而实现状态切换。

  // 播放/暂停音乐
const playMusic = useCallback(() => {
    isPlaying ? audioRef.current.pause() : audioRef.current.play()
    setIsPlaying(!isPlaying)
  }, [isPlaying])

通过 antd 的 Slider滑动条来改变播放进度:通过Slider自带 value={progress} 属性获取当前播放进度,从而设置audio的播放进度。

//进度改变触发onchange时间,调用该函数
  const sliderChange = useCallback((value) => {
    setIsChanging(true)
    const currentTime = value / 100 * duration / 1000
    setCurrentTime(currentTime * 1000)
    setProgress(value)
  }, [duration])

获取当前状态,切换播歌类型:

// 获取状态中的播放类型
    sequence: state.getIn(['player', 'sequence']),
// 点击切换播放类型
<button className="sprite_playbar btn loop" onClick={changeSequence}></button>
// 改变播放类型
  const changeSequence = () => {
    let currentSequence = sequence + 1
    if (currentSequence > 2) { currentSequence = 0 }
    dispatch(changeSequenceAction(currentSequence))
  }

使用 isChanging, setIsChanging = useState(false),来判断当前进度条是否正在改变,以便于当用户正在播放音乐并滑动滚动条时,滚动条可以滑动

利用 antd 的 Slider组件 自带的onChange和onAfterChange的属性可以得到进度条滑动的位置和滑动后结束的位置

使用useCallback减少渲染次数:

原理:把函数以及依赖项作为参数传入 useCallback,它将返回该回调函数的 memoized 版本,这个 memoizedCallback 只有在依赖项有变化的时候才会更新。

例如:

// 播放歌曲进度条部分
// 滑动中的位置
  const sliderChange = useCallback((value) => {
    setIsChanging(true)
    // 滑动滚动条时,实时更新时间的改变
    const currentTime = value / 100 * duration / 1000
    setCurrentTime(currentTime * 1000)
    setProgress(value)
  }, [duration])
// 滑动后的位置
  const sliderAfterChange = useCallback((value) => {
	//滑动进度条后的进度条时间
    const currentTime = value / 100 * duration / 1000
    audioRef.current.currentTime = currentTime
     // 重新更新进度条时间
    setCurrentTime(currentTime * 1000)
    setIsChanging(false)
	//如果没有播放音乐,当滑动滚动条后开始播放音乐
    if (!isPlaying) {
      playMusic()
    }
  }, [duration, isPlaying, playMusic])
  • 歌词的处理

实现:展示歌词部分使用的是 antd的 Message全局提示

原理:先获取到这首歌的全部歌曲,在 utils/parse-lyric下格式化歌词,原理就是将字符串转为数组,数组的每一项为 一个对象 { time, content }包含了时间及该时间的歌词。

六、遇到的问题

背景图片不能正常显示:

源代码:

 background-image: url(${require("@/assets/img/recommend-top-bg.png")});

解决方法:为图片添加.default

background-image: url(${<!--{cke_protected}{C}%3C!%2D%2D%20%2D%2D%3E-->require("@/assets/img/recommend-top-bg.png").default});

编写代码过程中无法将数据存储到redux的state中,但是看了react devtools 发现代码能够正常执行到action部分,在我编写了两遍 actionCreators.js 和 reducer.js 后发现是因为我没有在总的 store 中合并 reducer,留下悲伤的泪水。

滑动播放音乐的进度条时,进度条会短暂的回弹到滑动前位置。错误原因:在获取当前音乐播放时间时,利用setCurrentTime(e.target.currentTime * 1000),但是e.target.currentTime无法更加实时的获得当前滑动的数据,所以出现回弹。 解决方法:在滑动结束后的回调函数冲重新更新进度条时间。

  const sliderAfterChange = useCallback((value) => {
  	// 获取滑动进度条后的进度条时间
    const currentTime = value / 100 * duration / 1000
    // 设置当前时间
    audioRef.current.currentTime = currentTime
    setCurrentTime(currentTime * 1000)
  }, [duration])

七、github链接

react仿写网易云音乐项目

到此这篇关于React模仿网易云实现一个音乐项目详解流程的文章就介绍到这了,更多相关React网易云音乐内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • react native仿微信PopupWindow效果的实例代码

    在原生APP开发中,相信很多开发者都会见到这种场景:点击右上角更多的选项,弹出一个更多界面供用户选择.这种控件在原生开发中Android可以用PopupWindow实现,在iOS中可以用CMPopTipView,也可以自己写一个View实现.其类似的效果如下图所示: 实现思路分析: 要实现上面的视图,有很多种实现方式.前面的文章说过,要实现弹框相关的可以用React Native 提供的 Modal组件(Modal组件),使用Modal组件可以实现我们原生开发中的大多数效果. 要实现下拉三角,可

  • React Native仿美团下拉菜单的实例代码

    本文介绍了React Native仿美团下拉菜单的实例代码,最近也在学习React Native,顺便分享给大家 在很多产品中都会涉及到下拉菜单选择功能,用的最好的当属美团了,其效果如下: 要实现上面的效果,在原生中比较好做,直接使用PopWindow组件即可.如果使用React Native开发上面的效果,需要注意几个问题: 1. 在下拉的时候有动画过度效果: 2.下拉菜单出现后点击菜单项,菜单项可选择,并触发对应的事件: 3.下拉菜单中的项目可以配置: 要实现弹框效果,我们马上回想到使用Mo

  • React组件设计过程之仿抖音订单组件

    目录 前言 前期准备 实现后的组件效果 1. 组件设计思路 2. 实现 Myorder 组件 2.1 实现tab切换效果 2.2 获取数据 2.3 实现搜索功能 2.4 设置loading状态 2.5 实现Empty(空状态)组件 3. 实现 OederList 组件 4. 实现 OrderNote 组件 5. 实现 RecommendList 组件 最后 前言 作为数据驱动的领导者react/vue等MVVM框架的出现,帮我们减少了工作中大量的冗余代码, 一切皆组件的思想深得人心.组件就是对一

  • React项目仿小红书首页保姆级实战教程

    目录 前言 前期准备 项目预览 项目准备 工具 项目初始化 安装项目依赖 工程化src目录 api目录 assets目录 components目录 modules目录 pages目录,routes目录以及utils目录 页面设计思路 main.jsx App.jsx 搭建路由 首页组件分析 首页页面布局style.js Header组件 Footer组件 详情页页面分析 点赞效果实现 最后 前言 React 是一个用于构建用户界面的 Javascript库.主要用于构建UI,它起源于 Faceb

  • React模仿网易云音乐实现一个音乐项目详解流程

    目录 一.项目功能说明 二.最终效果 三.文件目录结构说明 四.项目技术栈 五.核心技术 六.遇到的问题 七.github链接 一.项目功能说明 暂停.播放歌曲 切换上一首.下一首歌曲 拖动进度条改变播放进度 随机播放.循环播放.单曲循环 实时展示歌词 切换不同分类的歌单.歌手.电台 实现推荐.排行榜.歌单.主播电台.歌手.新碟上架板块的展示 二.最终效果 首页: 排行榜: 歌单: 主播电台: 歌手: 新碟上架: 三.文件目录结构说明 assets:存放共用的css.font图标.image c

  • 利用spring boot如何快速启动一个web项目详解

    前言 基于我们创建好的lion项目,使用spring boot,我们就可以通过很少的一些配置,便可以启动这个项目.下面话不多说了,来一起看看详细的介绍吧. 方法如下: 1 引入Spring boot,我们打开lion父模块的pom文件,继承 spring boot的pom 2让lion-web模块依赖spring boot的web相关的jar包,打开lion-web项目下的pom文件,添加如下的依赖 3 添加spring boot入口启动类Application.java,这个类要房子lion-

  • vue模仿网易云音乐的单页面应用

    说明 一直想做一个基于VUE的项目,但是因为项目往往要涉及到后端的知识(不会后端真的苦),所以就没有一直真正的动手去做一个项目. 直到发现GitHub上有网易云音乐的api NeteaseCloudMusicApi,才开始动手去做. 仅仅完成了首页,登入,歌单,歌曲列表页. 项目地址 https://github.com/qp97vi/music 项目成功运行还要把后端api在本地运行 前端技术栈 vue2+vuex+vue-router+axios+mint-ui+webpack 遇到的问题

  • Android 控制车载蓝牙播放音乐详解流程

    需求:手机端音乐暂停和播放状态从服务端告诉客户端.设备端实现暂停.播放.上一首.下一首等功能 代码路径: packages/apps/Bluetooth/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerService.java packages/apps/Bluetooth/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerStateMachine.java pack

  • React TypeScript 应用中便捷使用Redux Toolkit方法详解

    目录 前言 背景 Redux-Toolkit 常规使用 优化方案 优化 useDispatch 和 useSelector 优化修改 redux 状态的步骤 总结 前言 本文介绍的主要内容是 Redux-Toolkit 在 React + TypeScript 大型应用中的实践,主要解决的问题是使用 createSlice 的前提下消费 redux 状态仍旧有点繁琐的问题. 阅读本文需要的前置知识:了解 React .Redux-Toolkit .TypeScript 的使用. 关于 Redux

  • React 首页加载慢问题性能优化案例详解

    学习了一段时间React,想真实的实践一下.于是便把我的个人博客网站进行了重构.花了大概一周多时间,网站倒是重构的比较成功,但是一上线啊,那个访问速度啊,是真心慢,慢到自己都不能忍受,那么小一个网站,没几篇文章,慢成那样,不能接受.我不是一个追求完美的人,但这样可不行.后面大概花了一点时间进行性能的研究.才发现慢是有原因的. React这类框架? 目前主流的前端框架React.Vue.Angular都是采用客户端渲染(服务端渲染暂时不在本文的考虑范围内).这当然极大的减轻了服务器的压力.相对的浏

  • React组件实例三大属性state props refs使用详解

    目录 一. State 1.概念 2.State的简单用法 3. JS绑定事件 4.react 绑定事件 5.react this指向问题 6.修改state值 7.代码简写 二.props 1.概念 2.传参的基础方法.运算符传参 三.refs 定义 字符串形式的ref.回调函数下ref.createRef 创建ref容器 一. State 1.概念 概念:state是组件对象最重要的属性,值是对象(可以包含多个key:value的组合),组件被称为状态机,通过更新组件的state来更新对应的

  • React的生命周期函数初始挂载更新移除详解

    目录 概述 constructor 初始 挂载 更新 移除 概述 在React中,生命周期函数指的是组件在某一个时刻会自动执行的函数 constructor 在类或组件创建的时候被自动执行,我们可以说它是生命周期函数,但它并不是React所特有的,所有的Es6对象都有这个函数,所以并不能说它是React的生命周期函数 初始 当数据发生变化时,render函数会被自动执行,符合我们对React生命周期函数的定义,所以它是React的生命周期函数,但在初始阶段,并不会有任何的React生命周期函数被

  • react框架next.js学习之API 路由篇详解

    目录 正文 使用方式 API 路由匹配 API 处理 API 配置 边缘计算支持 自定义 API 注意点 总结 正文 next.js 作为最热门的 react 框架,不过这么久了好像国内使用率一直不太高.最近在研究做个小项目正好做下笔记,有兴趣的可以一起来学习. next.js 首页标榜的 12 个特性之一就是 API routes,简单的说就是可以 next.js 直接写 node 代码作为后端服务来运行.因此我们可以直接使用 next.js 直接维护一个全栈项目,听起来很香的样子. 使用方式

  • autojs模仿QQ长按弹窗菜单实现示例详解二

    目录 引言 弹窗菜单 箭头 如何确认箭头方向? 调整popwindow的位置 调用方法如下 绘制箭头 修改颜色和圆角 给弹框菜单添加点击事件 弹框菜单点击事件引用弹框实例 环境 引言 上一节讲了列表和长按事件 autojs模仿QQ长按弹窗菜单 弹窗菜单 由粗到细, 自顶向下的写代码 我们现在要修改的文件是showMenuWindow.js function showMenuWindow(view) { let popMenuWindow = ui.inflateXml( view.getCont

随机推荐