0、项目规范
一、路由相关
npm i react-router-dom
npm i react-router-config // 用于配置路由映射的关系数组
1. 路由重定向
访问 /路径 =》 重定向到 /discover路径
2. 二级路由:
二、网络请求相关
npm i axios
页面中使用暴露 出来的request发送网络请求:
封装service:
config.js: 配置baseUrl、timeout等参数
const devBaseURL = "http://123.207.32.32:9001";
const proBaseURL = "http://123.207.32.32:9001";
export const BASE_URL = process.env.NODE_ENV === 'development' ? devBaseURL: proBaseURL;export const TIMEOUT = 5000;
request.js:创建一个axios实例暴露出去,供整个项目的所有页面使用
import axios from 'axios';
import { BASE_URL, TIMEOUT } from "./config";
const instance = axios.create({baseURL: BASE_URL,timeout: TIMEOUT
});
instance.interceptors.request.use(config => {// 1.发送网络请求时, 在界面的中间位置显示Loading的组件// 2.某一些请求要求用户必须携带token, 如果没有携带, 那么直接跳转到登录页面// 3.params/data序列化的操作return config;
}, err => {
});
instance.interceptors.response.use(res => {return res.data;
}, err => {if (err && err.response) {switch (err.response.status) {case 400:console.log("请求错误");break;case 401:console.log("未授权访问");break;default:console.log("其他错误信息");}}return err;
});export default instance;
三、redux相关
redux代码规范如下:
- 每个模块有自己独立的reducer,通过combineReducer进行合并;
- 异步请求代码使用redux-thunk,并且写在actionCreators中;
- redux直接采用redux hooks方式编写,不再使用connect;
npm i redux react-redux redux-thunk
使用redux提供的hook来简化代码:
import React, {memo, useEffect} from "react";
import {shallowEqual, useDispatch, useSelector} from "react-redux";
import {getTopBannerAction} from "./store/actionCreator";function HYRecommend(props) {const {topBanners} = useSelector((state) => {return {topBanners: state.recommend.topBanners}}, shallowEqual)// 组件和redux关联要做两件事:// 1. 获取数据// 2. 进行操作const dispatch = useDispatch()// 发送网络请求useEffect(() => {dispatch(getTopBannerAction())}, [dispatch])return (<div><h2>HYRecommend:{topBanners.length}</h2></div>)
}
export default memo(HYRecommend)/*function HYRecommend(props) {const {getBanners, topBanners} = propsuseEffect(() => {getBanners()}, [getBanners])return (<div><h2>HYRecommend: {topBanners.length}</h2></div>)
}
const mapStateToProps = (state) => {return {topBanners: state.recommend.topBanners}
}
const mapDispatchToProps = (dispatch) => {return {getBanners: () => {dispatch(getTopBannerAction())}}
}
export default connect(mapStateToProps, mapDispatchToProps)(memo(HYRecommend))*/
四、数据可变性的问题
在React开发中,我们总是会强调数据的不可变性:
- 无论是类组件中的state,还是redux中管理的state;
- 事实上在整个JavaScript编码过程中,数据的不可变性都是非常重要的;
数据的可变性引发的问题(案例):
- 我们明明没有修改obj,只是修改了info,但是最终obj也被我们修改掉了;
- 原因非常简单,对象是引用类型,它们指向同一块内存空间,两个引用都可以任意修改;
有没有办法解决上面的问题呢?
- 进行对象的拷贝即可:Object.assign或扩展运算符
这种对象的浅拷贝有没有问题呢?
- 从代码的角度来说,没有问题,也解决了我们实际开发中一些潜在风险;
- 从性能的角度来说,有问题,如果对象过于庞大,这种拷贝的方式会带来性能问题以及内存浪费;
有人会说,开发中不都是这样做的吗?
- 从来如此,便是对的吗?
认识ImmutableJS
为了解决上面的问题,出现了Immutable对象的概念:
- Immutable对象的特点是只要修改了对象,就会返回一个
新的对象,旧的对象不会发生改变;
但是这样的方式就不会浪费内存了吗?
- 为了节约内存,又出现了一个新的算法:Persistent Data
Structure(持久化数据结构或一致性数据结构);
当然,我们一听到持久化第一反应应该是数据被保存到本地或
者数据库,但是这里并不是这个含义:
- 用一种数据结构来保存数据;
- 当数据被修改时,会返回一个对象,但是新的对象会尽可
能的利用之前的数据结构而不会对内存造成浪费;
如何做到这一点呢?结构共享。
ImutableJS常见API
注意:我这里只是演示了一些API,更多的方式可以参考官网;
JavaScript和ImmutableJS直接的转换
-
对象转换成Immutable对象:Map;
-
数组转换成Immutable数组:List;
-
深层转换:fromJS;
-
Immutable类型转成:toJS();
ImmutableJS的基本操作:
- 修改数据:set
- 获取数据:get
在项目中,结合Redux管理数据:
- 1.使用redux-immutable中的combineReducers;
npm i redux-immutable
- 2.所有的reducer中的数据都转换成Immutable类型的数据;
npm i immutable
五、style相关
.CSS采用普通CSS和styled-component结合来编写(全局采用普通CSS、局部采用styled-component);
六、在项目中:使用redux保存网络请求获取的数据,并供页面使用的步骤
-
修改对应组件recommend中的store/reducers.js文件:
-
在store/constants.js文件中新增 常量:
-
封装api接口函数:
-
在store/actionCreator.js文件中新增getAction和changeAction函数:
-
在需要拿到数据的页面中的
useEffect hook中派发一个getAction,在getAction函数中会执行发送网络请求的代码,拿到响应数据:
-
然后执行changeAction函数:
在changeAction函数中会返回一个对象
{type: 'changeXXX',data: 发送网络请求得到的数据
},
,然后redux内部会执行reducers函数:更新redux的state对象中存储的数据
- 在需要使用数据的页面中,通过redux提供的useSelector hook 拿到redux中保存的数据,供页面展示使用: