基于 react 搭建的在线音乐播放器
该项目由 Create React App 搭建.
-
工程构建:Create React App
-
项目搭建:
- views: views 目录用于存放项目功能模块的页面,需要根据路由配置情况以及页面复杂程度大小分割子级目录
- config: config 目录存放一些配置目录,比如 API 信息以及 axios 拦截器设置
- router: 路由信息文件夹
- layout: 页面基本布局
- store: store 目录用于整合 views 中的 store
- components: components 目录用于存放非业务组件,或者在多个业务间都需要用到的功能组件
- common: common 目录用于存放一些公共 css 以及 js 工具方法
-
部分第三方库:
- 基础框架: react
- 前端路由: react-router[-dom] v4
- 数据管理: redux / react-redux / redux-thunk
- 路由同步 store:connected-react-router
- 组件按需加载: react-loadable
- 网络请求: axios
- css 预处理器: stylus
- 字体图标: antd Icon(实在是懒)
-
代码规范:
- eslint: airbnb (可参见根目录下的.eslintrc 文件)
- 缩进空行等设置可参见项目根目录.editorconfig 文件
- 使用 commitizen 规范 commit 提交
-
API:
- � 前期:AD`s API
- 后期:NeteaseCloudMusicApi
开发阶段:将NeteaseCloudMusicApi的服务在本机起起来,通过更改package.json
的 proxy 字段进行代理
部署到服务器:通过nginx实现,具体参见这篇文章
使用 axios 拦截器,配合connected-react-router
进行相应处理
// 添加响应拦截器
axios.interceptors.response.use(
response => response,
error => {
// 请求错误时做些事
const { status } = error.response
if (status === 400) {
// 原谅我没有modal组件
console.log('抱歉,系统开小差了')
}
if (status === 403) {
// 跳转到403
store.dispatch(push('/exception/403'))
}
if (status >= 404 && status < 422) {
// 跳转到404
store.dispatch(push('/exception/404'))
}
if (status <= 504 && status >= 500) {
console.log('服务器内部错误')
}
return Promise.reject(error)
}
)
原本是每次 dispatch 异步请求 action 时,先 dispatch 一个请求开始的 action,根据这个 action 改变的数据去 showLoading,请求结束完 dispatch 一个请求结束的 action,根据数据 hideLoading,但是全是重复劳动,每一个请求都要做一次。
有想过在 axios 拦截中进行 showLoading 以及 hideLoading,但存在明显缺陷:粒度太大,不能定位到某一个具体组件。
公司的项目使用的是 dva,其插件 dva-loading 可以自动处理 loading 状态,不用一遍遍地写 showLoading 和 hideLoading,并且每一个 model 均有独立的 loading,组件内部可以获取到,目前还在思考不使用 dva 如何实现同样效果。
- menu 菜单导航
- header 头部
- footer 底部
- main 内容区域
头部和底部固定,中间高度自适应的几种实现方式
- header/footer 通过 fixed 定位,container 高度为 100vh,上下 padding 为 header 与 footer 的高度,main 高度为 100%
header {
height: 30px;
position: fixed;
top: 0;
left: 0;
}
footer {
height: 60px;
position: fixed;
bottom: 0;
left: 0;
}
.container {
height: 100vh;
padding: 30px 0 60px 0;
}
.main {
height: 100%;
}
- header 以及 footer 使用 fixed 定位 main 使用 absolute 定位
header {
height: 30px;
position: fixed;
top: 0;
left: 0;
}
footer {
height: 60px;
position: fixed;
bottom: 0;
left: 0;
}
.container {
height: 100vh;
}
.main {
position: absolute;
top: 30px;
bottom: 60px;
}
3.普通流式布局,container 高度为 100vh,中间高度通过calc
计算得到
header {
height: 30px;
}
footer {
height: 60px;
}
.container {
height: 100vh;
}
.main {
height: calc(100vh - 30px - 60px);
}
发现音乐-歌单 tab 页的歌单图片较多,加载看起来比较卡慢,未优化之前效果如下
可以通过使用 loading 占位来进行过渡,如下,
主要是通过 LoadableImage 组件代替原生 img 标签,具体代码实现 /component/LoadableImage:
import React, { Component, Fragment } from 'react'
import Loading from '../Loading'
export default class LoadableImage extends Component {
constructor(props) {
super(props)
this.state = {
loading: true
}
}
handleImageLoaded = () => {
this.setState({
loading: false
})
}
render() {
const { loading } = this.state
const { imgUrl, altText } = this.props
const display = loading ? 'none' : 'block'
return (
<Fragment>
<Loading loading={loading}>
<img
src={imgUrl}
alt={altText}
onLoad={this.handleImageLoaded}
style={{ display }}
/>
</Loading>
</Fragment>
)
}
}
歌手详情收藏歌单歌词滚动歌曲播放切歌模式
封装轮播图组件react-tiny-swiepr抽象 layout 组件抽象 router 信息异步请求全局错误处理- loading 控制
- 合理划分 redux 结构
- 封装 message 组件
- 性能优化
路由按需加载- 动画优化
- 服务端渲染
git clone https://github.com/worldzhao/music-react.git
cd music-react
npm install
npm start
每学到一点新知识,新**,我都会来改进这个项目,欢迎 fork 和 star,如果你正在学习 react,通过一个比较综合的项目来实战也还是非常不错的。