Redux 单项数据流框架,其特色是严格的数据流控制,开发过程当中应遵循3个原则:react
Redux 应用中应保持数据源的惟一性,说白了整个应用中只保持一个 Store,全部组件的数据源就是这个 Store 上的状态,Store 是个树形结构,每每某一个组件或者模块的数据来源于 Store 上的某个节点。git
Redux 强调要改变 Store 的状态只能经过 action ,action 返回对象,提供给 Redux 完成新的状态的组装。github
这里的纯函数就是 Reducer ,其函数签名包含两个参数 state、action,顾名思义就是经过 action 去改变 state,通常来讲是返回一个新的 state,其函数签名大体以下export default (state = initialState, action) => {}
。redux
Reudx 包含 Store、State、Reudcer、action,主要为这四部分组成:bash
{ type: actionType, data: ooxx };
这里说一下 actionType:一个常亮,用来区分不一样的 action所谓聪明、傻瓜只是相对来讲,一样也叫容器组件和展现组件。 鉴于专业性,下文一概采用容器组件和展现组件的叫法。容器组件负责将 Store 中的状态,经过 props 传递给展现组件,展现组件只负责渲染页面,无需持有状态。将一个组件拆分为容器组件和展现组件是设计 React 组件的一种模式,和 Redux 无关。框架
上面讲到,Redux 负责管理状态,组件拆分为容器组件和展现组件。容器组件须要状态,状态来自哪呢?固然是 Redux 。 故,能够将 Redux 和组件作一个结合,达到更好的效果,那就是 react-redux,他帮助开发者抽取了可复用的容器组件,开发者只需关注展现组件便可。 相比于 Redux ,react-redux 多了 Provider 和 connect 两部分ide
理解 Provider 首先要知道 context ,也就是上下文。试想这样一种业务场景:一个多层嵌套的组件结构中,只有最里层的组件须要使用 store ,首先想到的是用 props 传递,为了把 store 从最外层传递到最里层,就要中间的全部组件都增长对 store的支持 ,这样无疑是灾难,很麻烦。React 提供了 context 的支持,就是说一个树型结构中的全部组件都能访问一个对象(上下文)。为了让树形结构支持 context ,须要父组件声明对 context 的支持, Provider 就提供了这样的功能(也是一个组件,增长了 context)。因此咱们会看到 Provider 须要传递一个 store 属性,而且位于根组件的位置,这样应用中全部的组件都会经过 context 共享这个 store 。react-redux 提供了建立 Store 的方法。函数
一个函数,负责展现组件和容器组件的链接。大体是这样export default connect(mapStateToProps, mapDispatchToProps)(SearchBar)
这里边实际上是两次函数的执行,首先 connect 函数执行并返回了另外一个函数而后执行,参数是展现组件。flex
其实 connect
在执行的过程当中实际上产生了一个无名的 React 组件,这个组件定制了 shouldComponentUpdate
函数的实现,实现逻辑是比对此次传递给内层展现组件的 props 和上一次的 props ,由于负责“组件看起来怎样”的展现组件是一个无状态的组件,他的渲染彻底由传入的 props 决定,若是 props 没有变化,那就能够认为渲染结果确定同样。就不须要通过 VirtualDOM 作渲染。ui
不难理解 react-redux 告诉咱们,展现组件仅仅负责展现,不须要持有任何状态,展现组件的全部 state、action 所有来源于 props ,容器组件经过 props 传递给展现组件。
export const HOMEPAGE_SHOWSEARCHBAR = 'HOMEPAGE/SHOWSEARCHBAR';
export const HOMEPAGE_MENU_PAGECHANGE = 'HOMEPAGE/MENU/PAGECHANGE';
复制代码
export const searchBarFetch = (text) => ({
type: HOMEPAGE_FETCH_SEARCHBAR,
text: text
});
export const updateHomePageMenuPage = (page) => ({
type: HOMEPAGE_MENU_PAGECHANGE,
currentPage: page
});
复制代码
const initialState = {
homepage: {
menuInfo: {
items: common.menuInfos,
currentPage: 0
},
gridInfos: [],
sections: [{
title: '',
data: []
}],
},
searchBar: {
text: '搜一下'
}
};
复制代码
export default (state = initialState, action) => {
switch (action.type) {
case HOMEPAGE_FETCH_SEARCHBAR:
{
return {
...state,
searchBar: {
text: action.text
}
};
}
case HOMEPAGE_MENU_PAGECHANGE:
{
return {
...state,
homepage: {
menuInfo: {
items: state.homepage.menuInfo.items,
currentPage: action.currentPage
},
gridInfos: state.homepage.gridInfos,
sections: state.homepage.sections
}
}
}
}
return state;
};
复制代码
const reducers = combineReducers({
homepageReudcer
});
export default createStore(reducers);
复制代码
class HomeMenu extends Component {
render() {
const {menuInfos, currentPage} = this.props;
const items = menuInfos.map(({title, icon}) => (<HomeMenuItem title={title} icon={icon} key={title}/>));
const pageCount = Math.ceil(items.length / 10);
let menuViews = [];
for (let i = 0; i < pageCount; i++) {
const itemSlices = items.slice(i * 10, i * 10 + 10);
const view = <View style={styles.itemsView} key={i}>
{itemSlices}
</View>
menuViews.push(view);
}
return (
<View style={styles.container}>
<ScrollView
horizontal
pagingEnabled={true}
showsHorizontalScrollIndicator={false}
onScroll={this._onScroll}>
{menuViews}
</ScrollView>
<PageControl
style={styles.pageControl}
numberOfPages={pageCount}
currentPage={currentPage}
currentPageIndicatorTintColor={color.primary}
pageIndicatorTintColor={color.gray}/>
<View style={styles.line}/>
<HomeGridView/>
<View style={styles.line}/>
</View>
);
}
_onScroll = (event) => {
const x = event.nativeEvent.contentOffset.x;
const page = Math.round(x / common.screen.width);
const {currentPage, setCurrentPage} = this.props;
if (currentPage !== page) {
setCurrentPage(page);
}
}
}
const styles = StyleSheet.create({
container: {
backgroundColor: 'white',
},
itemsView: {
flexDirection: 'row',
flexWrap: 'wrap',
width: common.screen.width
},
pageControl: {
margin: 10
},
line: {
backgroundColor: color.paper,
width: common.screen.width,
height: 10,
}
});
const mapStateToProps = (state) => ({menuInfos: state.homepageReudcer.homepage.menuInfo.items, currentPage: state.homepageReudcer.homepage.menuInfo.currentPage});
const mapDispatchToProps = (dispatch) => ({
setCurrentPage: (page) => {
dispatch(updateHomePageMenuPage(page));
}
})
export default connect(mapStateToProps, mapDispatchToProps)(HomeMenu)
复制代码