在 Taro 中可以自由地使用 React 生态中非常流行的数据流管理工具 Redux 来解决复杂项目的数据管理问题。而为了更方便地使用 Redux ,Taro 提供了与 react-redux API 几乎一致的包 @tarojs/redux 来让开发人员获得更加良好的开发体验。

    下文中示例代码均在 taro-redux-sample

    首先请安装 redux@tarojs/redux@tarojs/redux-h5,以及一些需要用到的 redux 中间件

    1. $ yarn add redux @tarojs/redux @tarojs/redux-h5 redux-thunk redux-logger
    2. # 或者使用 npm
    3. $ npm install --save redux @tarojs/redux @tarojs/redux-h5 redux-thunk redux-logger

    随后可以在项目 src 目录下新增一个 store 目录,在目录下增加 index.js 文件用来配置 store,按自己喜好设置 redux 的中间件,例如下面例子中使用 redux-thunkredux-logger 这两个中间件

    1. // src/store/index.js
    2. import { createStore, applyMiddleware } from 'redux'
    3. import thunkMiddleware from 'redux-thunk'
    4. import { createLogger } from 'redux-logger'
    5. import rootReducer from '../reducers'
    6. const middlewares = [
    7. thunkMiddleware,
    8. createLogger()
    9. ]
    10. export default function configStore () {
    11. const store = createStore(rootReducer, applyMiddleware(...middlewares))
    12. return store
    13. }

    接下来在项目入口文件 app.js 中使用 @tarojs/redux 中提供的 Provider 组件将前面写好的 store 接入应用中

    1. // src/app.js
    2. import Taro, { Component } from '@tarojs/taro'
    3. import { Provider } from '@tarojs/redux'
    4. import configStore from './store'
    5. import Index from './pages/index'
    6. import './app.scss'
    7. const store = configStore()
    8. class App extends Component {
    9. config = {
    10. pages: [
    11. 'pages/index/index'
    12. ],
    13. window: {
    14. navigationBarTitleText: 'Test'
    15. }
    16. }
    17. render() {
    18. return (
    19. <Provider store={store}>
    20. <Index />
    21. </Provider>
    22. )
    23. }
    24. }
    25. Taro.render(<App />, document.getElementById('app'))

    然后就可以开始使用了。如 redux 推荐的那样,可以增加

    • constants 目录,用来放置所有的 action type 常量
    • actions 目录,用来放置所有的 actions
    • reducers 目录,用来放置所有的 reducers例如我们要开发一个简单的加、减计数器功能

    新增 action type

    1. // src/constants/counter.js
    2. export const ADD = 'ADD'
    3. export const MINUS = 'MINUS'

    新增 reducer 处理

    1. // src/reducers/counter.js
    2. import { ADD, MINUS } from '../constants/counter'
    3. const INITIAL_STATE = {
    4. num: 0
    5. }
    6. export default function counter (state = INITIAL_STATE, action) {
    7. switch (action.type) {
    8. case ADD:
    9. return {
    10. ...state,
    11. num: state.num + 1
    12. }
    13. case MINUS:
    14. return {
    15. ...state,
    16. num: state.num - 1
    17. }
    18. default:
    19. return state
    20. }
    21. }
    1. // src/reducers/index.js
    2. import { combineReducers } from 'redux'
    3. import counter from './counter'
    4. export default combineReducers({
    5. counter
    6. })

    新增 action 处理

    1. // src/actions/counter.js
    2. import {
    3. ADD,
    4. MINUS
    5. } from '../constants/counter'
    6. export const add = () => {
    7. return {
    8. type: ADD
    9. }
    10. }
    11. export const minus = () => {
    12. return {
    13. type: MINUS
    14. }
    15. }
    16. // 异步的 action
    17. export function asyncAdd () {
    18. return dispatch => {
    19. setTimeout(() => {
    20. dispatch(add())
    21. }, 2000)
    22. }
    23. }

    最后,我们可以在页面(或者组件)中进行使用,我们将通过 tarojs/redux 提供的 connect 方法将 redux 与我们的页面进行连接

    1. // src/pages/index/index.js
    2. import Taro, { Component } from '@tarojs/taro'
    3. import { View, Text } from '@tarojs/components'
    4. import { connect } from '@tarojs/redux'
    5. import './index.scss'
    6. import { add, minus, asyncAdd } from '../../actions/counter'
    7. @connect(({ counter }) => ({
    8. counter
    9. }), (dispatch) => ({
    10. add () {
    11. dispatch(add())
    12. },
    13. dec () {
    14. dispatch(minus())
    15. },
    16. asyncAdd () {
    17. dispatch(asyncAdd())
    18. }
    19. }))
    20. class Index extends Component {
    21. config = {
    22. navigationBarTitleText: '首页'
    23. }
    24. render () {
    25. return (
    26. <View className='todo'>
    27. <Button className='add_btn' onClick={this.props.add}>+</Button>
    28. <Button className='dec_btn' onClick={this.props.dec}>-</Button>
    29. <Button className='dec_btn' onClick={this.props.asyncAdd}>async</Button>
    30. <View>{this.props.counter.num}</View>
    31. </View>
    32. )
    33. }
    34. }
    35. export default Index

    connect 方法接受两个参数 mapStateToPropsmapDispatchToProps

    • mapStateToProps,函数类型,接受最新的 state 作为参数,用于将 state 映射到组件的 props
    • mapDispatchToProps,函数类型,接收 dispatch() 方法并返回期望注入到展示组件的 props 中的回调方法