构建一个React-redux应用(知乎日报篇)

背景

本项目是采用 React+redux 实现的知乎日报的App,所有API均来自网络(若涉及侵权,请及时联系我删除)

运行

  • 获取 git clone https://github.com/Hancoson/react-redux-demo.git
  • 安装 npm install(yarn)
  • 启动 npm start
  • 构建 npm build

对应技术

  • 底层技术 React+redux+react-router
  • 编码规范 ES6
  • 构建工具 webpack
  • UI Antd
  • API 采用Yahoo跨域访问代理
  • 其他工具技术 React-hot-loadbabelwebpack-dev-server

技术实现

react

A JAVASCRIPT LIBRARY FOR BUILDING USER INTERFACES

state & props

  • props(属性)和state(状态)的改变都会触发render函数来更新界面;
  • 属性(props)是由父组件传递给子组件的;
  • 状态(state)是组件内部维护的数据,当状态发生变化的同时,组件也会进行更新。 当状态发生转换时会触发不同的钩子函数,从而让开发者有机会做出相应操作。

react

生命周期

1
2
3
4
5
6
//初始化阶段
getDefaultPropos //只调用一次,实力之间共享引用
getInitialState //初始化每个实例特有的状态
componentWillMount //render之前最后一次修改状态的机会
render //只能访问this.props和this.state,只有一个顶层组件,不允许修改状态和DOM输出
componentDidMount //成功render并渲染完成真实DOM后触发,可以修改DOM
1
2
3
4
5
6
//运行中阶段
componentWillReceiveProps //父组件修改属性触发,可以修改新属性,修改状态
shouldComponentUpdate //返回false会阻止render调用
componentWillUpeate //不能修改属性和状态
render //只能访问this.props和this.state,只有一个顶层组件,不允许修改状态和DOM输出
componentDidUpdate //可以修改DOM
1
2
//销毁阶段
componentWillUnMount //在删除组件之前进行清理操作,比如计时器和事件监听器。

组件化的开发思路

所谓组件,即封装起来的具有独立功能的UI部件

  • React推荐以组件的方式去重新思考UI构成,将UI上每一个功能相对独立的模块定义成组件, 然后将小的组件通过组合或者嵌套的方式构成大的组件,最终完成整体UI的构建。
  • 如果说MVC的思想让你做到视图-数据-控制器的分离,那么组件化的思考方式则是带来了UI功能模块之间的分离。

redux

redux主要由三部分组成:store,reducer,action。

先简单说一下 reduxreact 是怎么配合的。react-redux 提供了connectProvider两个好基友,它们一个将组件与redux关联起来,一个将store传给组件。组件通过dispatch发出actionstore根据actiontype属性调用对应的reducer并传入state和这个actionreducerstate进行处理并返回一个新的state放入storeconnect监听到store发生变化,调用setState更新组件,此时组件的props也就跟着变化。

Redux

核心代码

  • app入口文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import {Provider} from 'react-redux'
import {Router, hashHistory} from 'react-router'
import {syncHistoryWithStore} from 'react-router-redux'
……

// 给增强后的store传入reducer
const store = finalCreateStore(reducer);

// 创建一个增强版的history来结合store同步导航事件
const history = syncHistoryWithStore(hashHistory, store)

render(
<Provider store={store}>
<Router history={history} routes={routes}/>
</Provider>,
document.getElementById('app')
)
  • store
1
2
3
4
5
6
7
8
9
10
11
12
13
14
import thunk from 'redux-thunk' // redux-thunk 支持 dispatch function,并且可以异步调用它
import createLogger from 'redux-logger' // 利用redux-logger打印日志
import {createStore, applyMiddleware, compose} from 'redux' // 引入redux createStore、中间件及compose

const loggerMiddleware = createLogger()// 调用日志打印方法

const middleware = [thunk, loggerMiddleware]// 创建一个中间件集合

// 利用compose增强store,这个 store 与 applyMiddleware 和 redux-devtools 一起使用
const finalCreateStore = compose(
applyMiddleware(...middleware),
window.devToolsExtension ? window.devToolsExtension() : f => f
)(createStore)
……
  • reducer
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
……
const itemsReducer = (state = _default, action) => {

switch (action.type) {
case actionType.GETSUCCESS:
return action.data;

case actionType.EMPTYDATA:
return _default;
default:
return state;
}
};
……

// 默认获取数据
const defaultFetchData = () => {
return (dispatch) => {
return dispatch(fetchPosts(getDate()))
}
}

const getItems = state => {
……
}

//connect 连接react和redux
export default connect(
getItems,
{defaultFetchData, fetchData}
)(Items)

总结

因为整个项目组我是第一个用react+redux做项目的,遇到问题只能自己解决,如果不是在github上下载了别人的代码,我觉得自己是不可能按时完成任务的,它让我少走了很多弯路。写一个已经被写烂的todo demo和写一个完整的项目完全是两回事,所以我非常欣赏和感谢那些愿意分享自己代码的人,也会将自己的代码分享出来,希望对大家有帮助。

最后附上github地址https://github.com/Hancoson/react-redux-demo ,喜欢的麻烦帮我点个star,我会分享更多干货。