1、创建React项目
1.1、项目环境搭建
$ cnpm i create-react-app
$ create-react-app zhihu
1.2、安装依赖
$ cnpm i react-router-dom --save
$ cnpm i redux --save
$ cnpm i react-redux --save
$ cnpm i redux-thunk --save
$ cnpm i immutable --save
$ cnpm i redux-immutable --save
$ cnpm i axios --save
$ cnpm i antd --save
$ cnpm i @ant-design/icons --save
$ cnpm i styled-components --save
1.3、精简项目结构
- public
- src
- components 管理公共组件目录
- views 管理视图组件目录
- store 管理状态目录
- router 管理路由目录
- http 管理http请求目录
- static 管理静态资源文件目录
- App.js 根组件
- index.js 入口文件
- package.json
2、核心业务代码
2.1、样式组件
项目中的样式组件使用 styled-components 实现。
全局样式
创建 src/style.js 样式组件文件,示例代码如下:
import { createGlobalStyle } from 'styled-components'
export const GlobalStyle = createGlobalStyle`
html,body {
margin: 0px;
padding: 0px;
height: 100%;
background-color: #F6F6F6;
}
`
在 src/index.js 入口文件中,引入全局样式组件,示例代码如下:
import React from 'react'
import ReactDOM from 'react-dom'
import App from './App'
import { GlobalStyle } from './style'
ReactDOM.render(
<>
<GlobalStyle />
<App/>
</>
,document.getElementById('root'));
局部样式
以头部导航为例。
创建 src/views/Home/style.js 样式文件,示例代码如下:
import styled from 'styled-components'
export const HeaderWapper = styled.header.attrs({
title: '提示'
})`
height: 50px;
width: 100%;
background-color: #fff;
font-color: blue;
border-bottom: 1px solid #ccc;
&.header-top {
border-color: blue;
.title {
color: ${prop => prop.color};
}
}
.title{
color: ${prop => prop.color};
}
`
在 src/views/Home/index.jsx 中引入样式组件,示例代码如下:
import React, { Component } from 'react'
import { HeaderWapper } from './home'
export default class index extends Component {
render() {
return (
<div>
<HeaderWapper className="header-top" color="green" text="这是提示">
<div className="title">知乎</div>
</HeaderWapper>
<HeaderWapper className="header-bottom" color="pink">
<div className="title">知乎</div>
</HeaderWapper>
</div>
)
}
}
2.2、状态管理
2.2.1、创建状态管理结构
创建 reducers
以知乎项目为例,需要创建三个 reducer 函数,分别为:
userReducer.js 用户管理articleReducer.js 文件管理commentReducer.js 评论管理
新建 src/store/reducers 目录,并且分别创建三个文件:
reducers/userReducer.js ,示例代码:
import { Map } from 'immutable'
const initState = Map({
user: {
name: 'admin',
role: 1
}
})
const userReducer = (state = initState, action) => {
return state
}
export default userReducer
reducers/articleReducer.js ,示例代码:
import { Map, List } from 'immutable'
const initState = Map({
articleList: List([])
})
const articleReducer = (state = initState, action) => {
return state
}
export default articleReducer
reducers/commentReducer.js ,示例代码:
import { Map,List } from 'immutable'
import ActionType from '../actions'
const initState = Map({
commentList: List([])
})
const commentReducer = (state = initState, action) => {
let list = state.get('commentList')
switch(action.type){
case ActionType.INSERTCOMMENT:
return state.set('commentList', list.push(action.comment));
case ActionType.UPDATECOMMENT:
return state.set('commentList', list.splice(action.index,1,action.comment));
case ActionType.REMOVECOMMENT:
return state.set('commentList', list.splice(action.index,1));
}
return state
}
export default commentReducer
为了方便管理不同的操作类型,需要创建 src/store/actions.js 文件,示例代码如下:
const INSERTCOMMENT = 'insert_comment'
const UPDATECOMMENT = 'update_comment'
const REMOVECOMMENT = 'remove_comment'
const ActionType = {
INSERTCOMMENT,
UPDATECOMMENT,
REMOVECOMMENT
}
export default ActionType
整合 reducers
创建 src/store/reducers/index.js 文件,示例代码如下:
import { combineReducers } from "redux-immutable";
import articleReducer from './articleReducer';
import commentReducer from './commentReducer';
import userReducer from './userReducer';
const rootReducer = combineReducers({
atricle: articleReducer,
comment: commentReducer,
user: userReducer
})
export default rootReducer
创建 store 对象
创建src/store/index.js 文件,示例代码如下:
import { createStore,applyMiddleware } from 'redux'
import rootReducer from './reducers'
import thunk from 'redux-thunk'
const store = createStore(rootReducer, applyMiddleware(thunk))
export default store
2.2.2、组件中使用全局状态
创建 map 映射
创建 src/store/map 目录,并创建三个 .js 文件,分别为:
map/mapState.js ,示例代码如下:
const mapState = state => {
return {
user: state.getIn(['user','user']),
commentList: state.getIn(['comment','commentList']),
articleList: state.getIn(['article', 'articleList'])
}
}
export default mapState
map/mapDispatch.js ,示例代码如下:
import ActionType from '../actions'
const mapDispatch = dispatch => ({
insertComment(comment){
dispatch({
type: ActionType.INSERTCOMMENT,
comment
})
},
updateComment(index,comment){
dispatch({
type: ActionType.UPDATECOMMENT,
index,
comment
})
},
removeComment(index){
dispatch({
type: ActionType.REMOVECOMMENT,
index
})
}
})
export default mapDispatch
map/index.js ,示例代码如下:
import mapState from './mapState'
import mapDispatch from './mapDispatch'
export {
mapState,
mapDispatch
}
在组件中获取状态
修改 src/index.js 入口文件的代码:
import React from 'react'
import ReactDOM from 'react-dom'
import App from './App'
import { GlobalStyle } from './style'
import { Provider } from 'react-redux'
import store from './store'
ReactDOM.render(
<Provider store={store}>
<GlobalStyle />
<App/>
</Provider>
,document.getElementById('root'));
在组件内使用 props 对象获取映射的属性与方法,以 App.js 组件为例:
import React, { Component } from 'react'
import { connect } from 'react-redux'
import {mapState, mapDispatch} from './store/map'
class App extends Component {
//添加评论
addComment(){
this.props.insertComment({
text: '这是一条评论',
createTime: Date.now()
})
}
//修改评论
update(index,item){
item.text = '新的评论内容'
this.props.updateComment(index,item)
}
//删除评论
del(index){
this.props.removeComment(index)
}
render() {
return (
<div>
hello -- { this.props.user.name }
<button onClick={this.addComment.bind(this)}>添加评论</button>
<hr></hr>
{ this.props.commentList.map((item,index)=>(
<div key={index}>
{ item.text } , { item.createTime }
<button onClick={this.update.bind(this,index,item)}>修改</button>
<button onClick={this.del.bind(this,index)}>删除</button>
</div>
)) }
</div>
)
}
}
export default connect(mapState,mapDispatch)(App)
|