第一部分 :准备
1). 项目描述: 整体业务功能/功能模块/主体的技术/开发模式
2). 技术选型: 数据展现/用户交互/组件化, 后端, 前后台交互, 模块化, 项目构建/工程化, 其它
3). API接口: 接口的4个组成部分, 接口文档, 对/调/测接口
1.1 项目描述
1) 此项目为一个前后台分离的招聘的SPA, 包括前端应用和后端应用
2) 包括用户注册/登陆, 大神/老板列表, 实时聊天等模块
3) 前端: 使用 React 全家桶+ES6+Webpack 等技术
4) 后端: 使用 Node+express+mongodb+socketIO 等技术
5) 采用模块化、组件化、工程化的模式开发
1.2 技术选型
1.3 前端路由
1)注册
- /register
- register.jsx
2)登录
- /login
- login.jsx
3)主界面 main.jsx
① 老板主界面
- /laoban
- laoban.jsx
② 大神主界面
- /dashen
- dashen.jsx
③ 消息主界面
- /message
- message.jsx
④ 个人中心界面
- /personal
- personal.jsx
⑤ 老板信息完善界面
- /laobaninfo
- laoban-info.jsx
⑥ 大神信息完善界面
- /dashenindo
- dasheninfo.jsx
⑦ 聊天界面
- /chat/:userid
- chat.jsx
1.4 API接口
1.5 能从此项目中学到什么
1.5.1 流程及开发方法
1) 熟悉一个项目的开发流程
2) 学会模块化、组件化、工程化的开发模式
3) 掌握使用 create-react-app 脚手架初始化 react 项目开发
4) 学会使用 node+express+mongoose+mongodb 搭建后台开发
1.5.2 React插件或第三方库
1) 学会使用 react-router-dom 开发单页应用
2) 学会使用 axios 与后端进行数据交互
3) 学会使用 redux+react-redux+redux-thunk 管理应用组件状态
4) 学会使用 antd-mobile 组件库构建界面
5) 学会使用 mongoose 操作 mongodb 数据
6) 学会使用 express 搭建后台路由
7) 学会使用 socket.io 实现实时通信
8) 学会使用 blueimp-md5 对密码进行 MD5 加密处理
9) 学会使用 js-cookies 操作浏览器端 cookie 数据
1.6 git常用命令
* git config --global user.name "username" //配置用户名
* git config --global user.password "xx@gmail.com" //配置邮箱
* git init //初始化生成一个本地仓库
* git clone url //将远程仓库克隆下载到本地
* git add * //添加到暂存区
* git commit –m “message” //提交到本地仓库
* git remote add origin url //关联到远程仓库
* git push origin master //push 到远程
* git pull origin master //从远程 pull 更新
1.7. npm 常用命令
npm init //初始化当前应用包, 生成 package.json
npm install //根据 package.json 下载所有依赖包
npm install packageName --save //下载某个运行时依赖包
npm install packageName --save-dev //下载某个开发编译期依赖包
npm install packageName -g //全局下载某个依赖包
npm install package@version //下载指定版本的某个依赖包
npm info packageName //查看某个包有远程仓库中的相关信息
npm rm packageName --save //移除已下载的运行依赖包
npm rm packageName –save-dev //移除已下载的开发依赖包
npm list //查看安装的所有的包
npm help //查看命令的详细帮助
npm install -g cnpm --registry=https://registry.npm.taobao.org //安装淘宝镜像
npm config set registry="https://registry.npm.taobao.org" //将淘宝镜像设置为 npm 的默认仓库
npm run xxx //执行 package.json 的 scripts 中配置的命令
npm root -g //查看全局下载目录
第二部分 应用开发
2.1 开启项目开发
2.1.1 搭建项目
1) create-react-app 是 react 官方提供的用于搭建基于 react+webpack+es6 项目的脚手架
2) 操作: npm install -g create-react-app : 全局下载工具
create-react-app gzhipin-client :下载模板项目
cd gzhipin
npm start
访问: localhost:3000
2.1.2 编码测试与打包发布项目
1) 编码测试
npm start
访问: http://localhost:3000
编码, 自动编译打包刷新(live-reload), 查看效果
2) 打包发布
npm run build
npm install -g serve
serve build
访问: http://localhost:5000
2.2 功能需求分析
对功能模块进行分析说明
2.3 项目(前端)源码目录设计
- src //客户端代码文件夹
- api //ajax请求相关模块文件夹
- assets //公共资源文件夹
- components //UI组件模块文件夹
- containers //容器组件模块文件夹
- redux //redux相关模块文件夹
- utils //工具模块文件夹
- index.js //入口JS
2.4 引入 antd-mobile
2.4.1 下载组件库包
npm install antd-mobile --save
2.4.2 页面处理:index.html
移动端点击延迟0.3秒问题 (用fastclick库)
<script src="https://as.alipayobjects.com/g/component/fastclick/1.0.6/fastclick.js"></script>
<script>
if ('addEventListener' in document)
{
document.addEventListener('DOMContentLoaded', function()
{
FastClick.attach(document.body); }, false); }
if(!window.Promise) {
document.writeln(
'<script src="https://as.alipayobjects.com/g/component/es6-promise/3.2.2/es6-promise.min.js" '+'>'+'<'+'/'+'script>'
);
}
</script>
2.4.3 实现组件的按需打包
- 下载依赖模块
npm install --save-dev babel-plugin-import react-app-rewired
- 定义加载配置的 js 模块:config-overrides.js
const {injectBabelPlugin} = require('react-app-rewired');
module.exports = function override(config, env) {
config = injectBabelPlugin(['import', {libraryName: 'antd-mobile', style: 'css'}], config);
return config;
}
修改配置:package.json
"scripts": {
"start": "react-app-rewired start",
"build": "react-app-rewired build",
"test": "react-app-rewired test --env=jsdom",
"eject": "react-scripts eject"
}
2.4.4 在应用中使用 antd组件
import React from 'react'
import ReactDOM from 'react-dom'
import {Button} from 'antd-mobile'
ReactDOM.render( <Button type='primary'>Test</Button>, document.getElementById('root') )
2.4.5 运行测试出现问题
①此时运行项目后会出现问题,运行npm start或者yarn start 报错injectBabelPlugin is not a function
原因是react-scripts 升级到 2.1.2 以后破坏了 react-app-rewired
解决方法,对react-scripts进行降级处理
yarn add react-app-rewired@2.0.2-next.0
②create-react-app : 无法加载文件 C:\Users\H . Y\AppData\Roaming\npm\create-react-app.ps1,因为在此系统上禁止运行脚本。有关详细信息,请参阅 https:/go.microsoft.com/fwlink/?LinkID=135170 中的 about_Execution_Policies。
解决方法:
管理员运行Windows PowerShell
输入`set-ExecutionPolicy RemoteSigned` Enter
再输入`A` Enter
最后`get-ExecutionPolicy`
再回到项目中运行create-react-app xx就可以了
2.4.6 应用中使用的组件
2.5 引入路由
2.5.1 下载路由
npm install --save react-router-dom
2.5.2 路由组件
containers/main/main.jsx
containers/login/login.jsx
containers/register/register.jsx
2.5.3 映射路由 index.js
import React from 'react'
import ReactDOM from 'react-dom'
import {HashRouter,Route,Switch} from 'react-router-dom'
import Register from './containers/regiser/regiser'
import Main from './containers/main/main'
import Login from './containers/login/login'
ReactDOM.render( (
<HashRouter>
<Switch>
<Route path='/register' component={Register}></Route>
<Route path='/login' component={Login}></Route>
<Route component={Main}></Route>
</Switch>
</HashRouter>
), document.getElementById('root') )
2.6 引入redux
2.6.1 下载相关依赖包
npm install --save redux@3.7.2 react-redux redux-thunk
npm install --save-dev redux-devtools-extension
注意: redux 不能下载最新版本
2.6.2 reducers:redux/reducers.js
/**
* 包含n个reducer函数:根据老的state和指定的action返回一个心的state
*/
import {combineReducers} from 'redux'
function xxx(state=0,action){
return state
}
function yyy(state=0,action){
return state
}
export default combineReducers({
xxx,
yyy
})
//向外暴漏的结构:{xxx:0,yyy:0}
2.6.3 store:redux/store.js
/**
* redux最核心的管理对象模块
*/
import { createStore, applyMiddleware } from "redux";
import reducers from './reducers'
import thunk from 'redux-thunk'
import {composeWithDevTools} from 'redux-devtools-extension'
//向外暴漏store对象
export default createStore(reducers,composeWithDevTools(applyMiddleware(thunk)))
2.6.4 入口JS:index.js
import React from 'react'
import ReactDOM from 'react-dom'
import {HashRouter,Route,Switch} from 'react-router-dom'
import Register from './containers/register/register'
import Main from './containers/main/main'
import Login from './containers/login/login'
import {Provider} from 'react-redux'
import store from './redux/store'
ReactDOM.render( (
<Provider store={store}>
<HashRouter>
<Switch>
<Route path='/register' component={Register}></Route>
<Route path='/login' component={Login}></Route>
<Route component={Main}></Route>
</Switch>
</HashRouter>
</Provider>
), document.getElementById('root') )
2.7 注册/登录界面
2.7.1 Logo组件
1)引入logo图片
2) components/logo/logo.jsx
import React, { Component } from 'react'
import logo from './logo.png'
import './logo.less'
export default class Logo extends Component {
render() {
return (
<div className="logo-container">
<img src={logo} alt="logo" className='logo-img'/>
</div>
)
}
}
- components/logo/logo.less
.logo-container {
text-align: center;
margin-top: 10px;
margin-bottom: 10px; .
.logo-img {
width: 240px; height: 240px;
}
}
2.7.2 注册组件
import React, { Component } from 'react'
import {NavBar,InputItem,WingBlank,List,WhiteSpace,Radio,Button} from 'antd-mobile'
import Logo from '../../components/logo/logo'
const ListItem=List.Item
export default class Register extends Component {
state={
username:'', //用户名
password:'',// 密码
password2:'',//确认密码
type:'dashen'//用户类型名称
}
register=()=>{
console.log(this.state)
}
//处理输入数据的改变:更新对应的状态
handleChange=(name,val)=>{
//更新状态
this.setState({
[name]:val //要求name变量的值 name相当于字符串,
})
}
toLogin=()=>{
this.props.history.replace('/login')
}
render() {
const {type}=this.state
return (
<div>
<NavBar>硅 谷 直 聘</NavBar>
<Logo/>
<WingBlank>
<List>
<InputItem onChange={val=>{this.handleChange('username',val)}}>用户名:</InputItem>
<WhiteSpace/>
<InputItem type='password'onChange={val=>{this.handleChange('password',val)}}>密 码:</InputItem>
<WhiteSpace/>
<InputItem type='password'onChange={val=>{this.handleChange('password2',val)}}>确认密码:</InputItem>
<WhiteSpace/>
<ListItem>
<span>用户类型:</span>
<Radio checked={type==='dashen'} onChange={()=>this.handleChange('type','dashen')}>大神</Radio>
<Radio checked={type==='laoban'} onChange={()=>this.handleChange('type','laoban')}>老板</Radio>
</ListItem>
<WhiteSpace/>
<Button type='primary' onClick={this.register}>注 册</Button>
<Button onClick={this.toLogin}>已有账户</Button>
</List>
</WingBlank>
</div>
)
}
}
2.7.3 登录组件
import React, { Component } from 'react'
import {NavBar,InputItem,WingBlank,List,Button,WhiteSpace} from 'antd-mobile'
import Logo from '../../components/logo/logo'
export default class Register extends Component {
state={
username:'', //用户名
password:'',// 密码
}
login=()=>{
console.log(this.state)
}
//处理输入数据的改变:更新对应的状态
handleChange=(name,val)=>{
//更新状态
this.setState({
[name]:val //要求name变量的值 name相当于字符串,
})
}
toRegister=()=>{
this.props.history.replace('/register')
}
render() {
return (
<div>
<NavBar>硅 谷 直 聘</NavBar>
<Logo/>
<WingBlank>
<List>
<InputItem placeholder='请输入用户名' onChange={val=>{this.handleChange('username',val)}} >用户名:</InputItem>
<WhiteSpace/>
<InputItem placeholder='请输入密码' type='password'onChange={val=>{this.handleChange('password',val)}}>密 码:</InputItem>
<WhiteSpace/>
<WhiteSpace/>
<Button type='primary' onClick={this.login}>登 录</Button>
<Button onClick={this.toRegister}>还没有账户</Button>
</List>
</WingBlank>
</div>
)
}
}
网友评论