前言
本文是个人对慕课网《React技术栈仿大众点评WebApp》的图文总结。
一、项目初始化
(一)初始化项目(npm init)
(二)安装webpack/webpack-dev-server/react/react-dom插件
二、webpack的配置
(一)webpack.config.js
- HtmlWebpackPlugin
作用:自动把html与bundle.js挂钩,这样我们就不必手动在index.html下引入bundle.js
- OpenBrowserPlugin
作用:启动webpack-dev-server后自动打开浏览器
- inline(webpack-dev-server下默认启动)
作用:启动hot reload,即热更新功能。
关闭热更新的方式:
或者在devServer中进行配置:
- HotModuleReplacementPlugin(简称HMR)
作用:启动模块热加载,即只更新变更的内容,避免浏览器重新渲染。
首先,什么是Module:
这里需要注意,在devServer里将hot设置为true后,还需要在plugins里通过new的方式启动HMR,否则会报错:
但是如果通过cli命令行的方式启动,即:–hot,则无需如此操作。
(HMR启动成功)。
- 配置devserver
注意,根据文档,progress(显示进度)/color(显示颜色)是需要以cli命令行里的形式进行配置:
(二)webpack.production.config.js
- plugins插件的配置
(1)BannerPlugin
作用:在打包后的文件内注入banner信息:
效果:
(2)HtmlWebpackPlugin
作用:自动将生成的js等文件与指定的html挂钩,我们就不再需要手动到html里去通过\<script>标签引入bundle.js文件。
(3)OccurrenceOrderPlugin/UglifyJsPlugin
作用:压缩JS模块代码
注意:这两个在webpack4的生产模式下是自动启动的,无需额外配置。
- 生产环境下,提取公共模块代码
(1)entry入口分开app和vendor两个入口处理:
其中app代表我们自己写的业务代码;vendor代表依赖包的代码,来源是package.json里的dependencies。
配置好后,在根目录下新建一个空文件夹build,然后执行npm run build命令:
成功打包后,在build文件夹下面可以看到,我们import或者require的依赖包代码都被打包到vendor.js里,业务代码则在app.js里。
(三)关于全局变量process.dev.NODE_DEV的坑
- 在package.json的scripts里,通过SET NODE_ENV=development的方式设置node里的process.dev.NODE_DEV全局变量:
- 在webpack.config.js里设置全局变量__DEV__来判断当前环境是否为dev:
- 然而这里有个坑,测试发现,webpack.config.js里所获取到的process.env.NODE_ENV和在其他js文件下获取到的不一样:
控制台打印出来发现,两个是不对等的:
- 实际上,在webpack.config.js里获取到的NODE_DEV为”development “,后面还有个空格,而这个空格产生的原因是我们在package.json的scripts里写下的:
- 把空格去掉再试一下:
这下在webpack.config.js里就完全匹配了。
三、react性能优化
(一)react-addons-perf
通过在浏览器控制台,在app跑起来之前Perf.start()锚点,然后运行一段时间后,再Perf.stop(),然后Perf.printWasted()来讲浪费性能的组件打印出来。
四、redux状态管理
(一)安装redux/redux-thunk/react-redux
(二)创建store文件夹,同时创建state.js/reducers.js/actions.js/store.js
–store
—-state.js // 用于存放state的初始状态
—-reducers.js // 通过switch对不同的输入return不同的输出(纯函数,本身并不改变任何state)
—-actions.js // 定义不同的操作(每个操作返回一个)
—-store.js // 创建store(一般会在此引入中间件)
- state.js
- reducers.js
(1)引入combineReducers来处理多个reducer的情况
- actions.js
- store.js
(1)thunk是redux里一个中间件,用于处理异步dispatch
(注:因store.dispatch本来只能接受action对象作为参数)
(三)在根目录入口文件里引入store
注:Provider的作用是将store作为全局props,这样后面所有的组件都能获取。
(四)在需要用到store的组件里引入react-redux
同时,把actions也引入。
这里mapStateToProps和mapDispatchToProps的作用分别是把state和dispatch映射到props里。
这样,就能在componentDidMount里通过this.props获取到dispatch。
同时也能在render里获取state了。
(五)在需要dispatch的地方执行action即可触发redux
这里总结起来一幅图:
(六)Redux DevTools的使用
- 在谷歌商店里下载redux-devtools
安装成功后,在chrome开发者模式下可以看到Redux的选项。
- 更新store.js里的相关配置,引入compose来合并thunk中间件
- 查看效果
五、fetch基础
(一)安装whatwg-fetch和es6-promise依赖
(二)app目录下创建fetch文件夹
创建test.js
(三)封装get和post请求
六、数据mock
这部分使用node里的后端框架koa来实现。
(一)安装koa
(二)在根目录下创建mock文件夹,里面新建server.js
- 配置server.js
注:根据koa2的文档,koa引入后需要通过new构造的方式创建。
- 在webpack.config.js的devServer里配置端口代理
备注:这是因为我们在上面app.listen()里监听的是3000端口,而我们的项目是在8080端口运行的,如果从8080端口往3000端口发送http请求的话会遇到跨域的问题,所以这里通过devServer里proxy代理的方式解决。
- 在package.json里的script脚本里增加mock命令
- 执行npm run mock
看到这样即代表mock的server已经跑起来了。
- 到组件里试试发送get和post请求
七、首页制作
(一)首部header组件
(二)轮播图
创建轮播组件Category.jsx
根据react-swipe文档,安装相关依赖包
- 根据文档编写ReactSwipe内容
- 编写轮播参数
- 通过this.state.index来控制轮播序号的变化
- 效果
(三)超值特惠
(四)推荐列表(猜你喜欢)
- 如何在koa2里获取router里的url中传递的参数?
方法如下:
注意,这里的console打印出来并不是在浏览器内部,而是在命令窗里:
- react中如何获取dom元素?可以用refs:
- 实现滚动到底部自动加载数据的功能
原理是在HomeLoadMore组件里,通过监听scroll事件设定定时器,利用getBoundingClientRect的api实现。
八、城市页制作
城市页编写中,由于需要获取及修改城市信息,所以需要用到redux及localStore。
- 使用bindActionCreators将setCity与dispatch绑定起来,然后通过mapDispatchToProps及connect组件传递到props里:
- 在changeFn里去执行通过props获取的setCity这个dispatch,改变redux中的cityInfo这个state,然后再同步改变本地缓存:
- 查看效果
- 功能补充:在更改城市后,应当跳转到首页
注意:在react-router-dom里,是通过this.props.history.push()来实现。
九、搜索页制作
(一)更新轮播组件Category,加入Link组件
(二)更新routerMap.jsx里的路由设置
上面更新好轮播组件的Link组件后,在首页点击轮播小图会进入到search路由,但是发现结果被分配到404页面了:
这是因为我们在routerMap.jsx里的路由设置的问题:
这里我们需要为search配置可选路由参数:
在react-router旧版本里,是通过括号来实现的:
但是这在react-router v4后不行了,要改为
(三)完成搜索栏功能
这里我们先把之前在HomeHeader里的input改为HomeSearchInput组件,然后通过onKeyUp监听用户输入内容:
注意,这里的重点是,在当用户按下回车(即keyCode为13时),我们要跳转到搜索页,而在HomeSearchInput组件里是无法获取this.props.history的(react-router-dom里,只有在router的component关联的组件里才能获取props.history),所以我们需要额外安装一个history依赖包:
然后,通过createHashHistory函数,来实现路由跳转。
(四)查看效果
十、详情页制作
(一)完成效果
(二)编写过程和前面类似,不赘述,有几个值得注意的:
- react中插入html元素的方式
通过dangerouslySetInnerHTML的接口来实现。
- 星级的实现方式:
十一、登录页
(一)完成效果
(二)需要注意的几点:
- redux中state为对象的更新方式
十二、购买和收藏功能
(一)完成效果:
(二)值得注意的地方:
十三、用户中心
(一)完成效果
(二)这部分制作和前面的类似,并无什么需要注意的。
十四、评价(用户中心)
完成后的效果: