在 Taro 中使用 Redux
前言
读了上篇文章,相信大家已经掌握了初步的 Taro 开发技能了,本文将带领大家结合 Redux 完善一个 Todolist。
首先,我们得对 Redux 有个初步的了解。Redux 是 JavaScript 状态容器,提供可预测的状态管理。一般来说,规模比较大的小程序,其页面状态和数据缓存等都需要管理很多的东西,这时候引入 Redux 可以方便的管理这些状态,同一数据,一次请求,应用全局共享。
而 Taro 也非常友好地为开发者提供了可移植的 Redux 。
依赖
为了更方便地使用 Redux,Taro 提供了与 react-redux API 几乎一致的包 @tarojs/redux 来让开发人员获得更加良好的开发体验。
开发前需要安装 redux 和 @tarojs/redux ,开发者可自行选择安装 Redux 中间件,本文以如下中间件为例:
$ yarn add redux @tarojs/redux redux-logger# 或者使用 npm$ npm install --save redux @tarojs/redux redux-logger
示例
下面通过丰富上一篇文章的 Todolist 快速上手 Redux 。
目录结构
首先通过目录划分我们的store/reducers/actions。
分别在三个文件夹里创建index.js,作为三个模块的入口文件。首先来看看store/index.js里面的内容。reducers和actions里面的内容我们需要规划好功能之后再来处理。
// store/index.jsimport { createStore, applyMiddleware } from 'redux'// 引入需要的中间件import thunkMiddleware from 'redux-thunk'import { createLogger } from 'redux-logger'// 引入根reducersimport rootReducer from '../reducers'const middlewares = [thunkMiddleware,createLogger()]// 创建 storeexport default function configStore () {const store = createStore(rootReducer, applyMiddleware(...middlewares))return store}
编写 Todos
首先,定义好store,然后在app.js中引入。使用@tarojs/redux中提供的Provider组件将前面写好的store接入应用中,这样一来,被Provider包裹的页面都能访问到应用的store。
Provider 组件使组件层级中的 connect() 方法都能够获得 Redux store。
import Taro, { Component } from '@tarojs/taro'import { Provider } from '@tarojs/redux'import configStore from './store'import Index from './pages/index'import './app.scss'const store = configStore()class App extends Component {...render () {return (<Provider store={store}><Index /></Provider>)}}
接下来我们正式开始规划 Todos 应用的主要功能。
首先我们可以新建constants文件夹来定义一系列所需的action type常量。例如 Todos 我们可以先增加ADD和DELETE两个action type来区分新增和删除 Todo 指令。
// src/constants/todos.jsexport const ADD = 'ADD'export const DELETE = 'DELETE'
然后开始创建处理这两个指令的reducer。
// src/reducers/index.jsimport { combineReducers } from 'redux'import { ADD, DELETE } from '../constants/todos'// 定义初始状态const INITIAL_STATE = {todos: [{id: 0, text: '第一条todo'}]}function todos (state = INITIAL_STATE, action) {// 获取当前todos条数,用以id自增const todoNum = state.todos.lengthswitch (action.type) {// 根据指令处理todoscase ADD:return {...state,todos: state.todos.concat({id: todoNum,text: action.data})}case DELETE:let newTodos = state.todos.filter(item => {return item.id !== action.id})return {...state,todos: newTodos}default:return state}}export default combineReducers({todos})
接着在action中定义函数对应的指令。
// src/actions/index.jsimport { ADD, DELETE } from '../constants/todos'export const add = (data) => {return {data,type: ADD}}export const del = (id) => {return {id,type: DELETE}}
完成上述三步之后,我们就可以在 Todos 应用的主页使用相应action修改并取得新的store数据了。来看一眼 Todos 的index.js。
// src/pages/index/index.jsimport Taro, { Component } from '@tarojs/taro'import { View, Input, Text } from '@tarojs/components'import { connect } from '@tarojs/redux'import './index.scss'import { add, del } from '../../actions/index'class Index extends Component {config = {navigationBarTitleText: '首页'}constructor () {super ()this.state = {newTodo: ''}}saveNewTodo (e) {let { newTodo } = this.stateif (!e.detail.value || e.detail.value === newTodo) returnthis.setState({newTodo: e.detail.value})}addTodo () {let { newTodo } = this.statelet { add } = this.propsif (!newTodo) returnadd(newTodo)this.setState({newTodo: ''})}delTodo (id) {let { del } = this.propsdel(id)}render () {// 获取未经处理的todos并展示let { newTodo } = this.statelet { todos, add, del } = this.propsconst todosJsx = todos.map(todo => {return (<View className='todos_item'><Text>{todo.text}</Text><View className='del' onClick={this.delTodo.bind(this, todo.id)}>-</View></View>)})return (<View className='index todos'><View className='add_wrap'><Input placeholder="填写新的todo" onBlur={this.saveNewTodo.bind(this)} value={newTodo} /><View className='add' onClick={this.addTodo.bind(this)}>+</View></View><View>{ todosJsx }</View></View>)}}export default connect (({ todos }) => ({todos: todos.todos}), (dispatch) => ({add (data) {dispatch(add(data))},del (id) {dispatch(del(id))}}))(Index)
最后来看一眼实现的效果:
小结
本章我们结合 Redux 丰富了一个 Todolist,通过梳理文件目录结构,规划 Todolist 功能,再细化到每一个文件的具体代码,让读者们深入浅出地了解到如何在 Taro 内结合 Redux 开发应用。
诚然,该文只是提供一种选型建议,是否需要在应用中使用状态管理框架,是否选用 Redux 作为应用的状态管理框架,还需要具体问题具体分析。如果你是在搭建类似商城这样的大型应用,我们非常建议你采用 Redux 管理数据状态,而譬如开发单页应用这类小型的站点,使用 Redux 则有可能会增加你的工作量哦。
