一、微信小程序自身的应用状态是怎样定义的呢?
page({ data: { item: '', isLoading: true }, onLoad: function(){ this.setData({ isLoading: false }) } })
二、为什么使用应用状态管理工具? 同一数据,一次请求,应用全局共享。 MVVM架构开发中清晰的数据流向——单向数据流。 将分散在不同页面的数据与应用状态统一管理,共享数据与状态变化。 适应组件化、模块化开发的数据结构,提高代码重复使用率、提高开发效率。 三、应用状态管理工具有哪些? 前端MVVM架构基础库有很多,目前主流的有React、Vue、Angular,不同的库有不同的应用状态管理方案,比如React常用的Flux,Redux,Mobx,Vue的Vuex,Angular的ngrx/store,Redux并不是React的专属,而是针对Redux有最优的解决方案,当然Redux同样也能移植到其他框架使用,比如可以在微信小程序中使用。 四、微信小程序如何选择应用状态管理工具库? 目前微信有移植的Redux与Mobx来作为应用状态管理,Redux 和 Mobx 都是当下比较火热的数据流模型,一个背靠函数式,似乎成为了开源界标配,一个基于面向对象,低调的前行。 函数式 vs 面向对象 函数式的优点: 将数据和处理逻辑分离,代码更加简洁,模块化,可读性好 易测试、易维护,测试环境容易模拟 逻辑代码可复用性强 相对比面向对象的编程: javascript的弱类型,表明它基于对象,不适合完全函数式表达。 数学思维和数据处理适合用函数式,而业务逻辑的处理适合用面向对象。 逻辑严谨的函数式编程相当完美,但为了实现具体业务功能不得不写更多细粒度代码来实现,而面向对象的方式更为简洁和灵活。 Redux vs Mobx 那么具体到这两种模型,又有一些特定的优缺点呈现出来。 先来看 Redux 的特点:
reducer
import { combineReducers } from 'redux' import { createReducer } from 'redux-immutablejs' import { fromJS } from 'immutable' import { EXAMPLE } from '../constants'
const example = createReducer(fromJS({ title: "项目构建成功" }),{ [EXAMPLE]: (state, action) => { return state.merge({ title: action.payload.title }) } })
const rootReducer = combineReducers({ example })
export default rootReducer
action
import { EXAMPLE } from '../constants'
function example(val){ return { type: EXAMPLE, payload: { title: val } } }
export function changeTitle(val){ return (dispatch, getState) => { dispatch(example(val)) } }
声明式编程 reducer 纯函数 action 无副作用 不可变数据 immutable 对比Mobx:
var extendObservable = require('../libs/mobx').extendObservable; var apiPath = require('../config/apiPath') var {formatTime} = require('../utils/tool')
var app = getApp()
var userInfo = function(){ extendObservable(this,{ title: '我的预约', data: {}, order: [] }) this.receive = function(){ var that = this app.getUserInfo(function (userInfo) { that.data = userInfo }) } this.getUserOrder = function(){ var that = this wx.request({ url: apiPath.GETUSERORDER, method: 'GET', header: { 'Authorization': `Bearer ${wx.getStorageSync('token') || []}`, 'Content-Type': 'application/json' }, success:function(json){ if(json.statusCode == 200){ that.order = json.data } }, fail:function(e){ console.log(e) } }) } }
数据流流动不自然,只有用到的数据才会引发绑定,局部精确更新,但免去了粒度控制烦恼。 想要时间回溯能力需要自建回溯数据较复杂,因为数据只有一份引用。 自始至终一份引用,不需要 immutable,也没有复制对象的额外开销。 数据流动由函数调用一气呵成,便于调试。 由于没有 magic,所以没有中间件机制,没法通过 magic 加快工作效率(这里 magic 是指 action 分发到 reducer 的过程)。 完美支持 typescript。 项目中如何选择 两者还有更本质的区别在于Redux将state与action互相独立,因此一个action可以将数据分发到多个state上,多个state都属于全局唯一的store中;而Mobx中action属于 store定义的object对象,因此只能对自身的state进行数据处理。越复杂的项目Redux的优势越明显。 从目前经验来看,建议前端数据流不太复杂的情况,使用 Mobx,因为更加清晰,实现同一业务的代码更少;如果前端数据流极度复杂,建议使用 Redux+immutable,通过中间件减缓巨大业务复杂度。另外,用Mobx的时候可以使用typescript来辅助。 五、在小程序中的使用Mobx 在小程序项目中由于小程序框架自身的特性,组件化使用较为复杂,因此不会将页面切分成细粒度组件,因此使用Mobx对于小程序来说要更为灵活。 index.js
var observer = require('../../libs/observer').observer; var Toast = require('../../components/toast/index')
Page(observer(Object.assign({}, Toast, { props: { userInfo: require('../../stores/userInfo').default }, onLoad: function () { this.props.userInfo.receive() wx.setNavigationBarTitle({ title: '我的' }) }, onShow: function (){ this.props.userInfo.getUserOrder() } })))
index.wxml
<import src="../../components/toast/index.wxml" /> <template is="zan-toast" data="{{ zanToast }}"></template> <view class="container"> <view class="userinfo"> <image class="userinfo-avatar" src="{{props.userInfo.data.avatarUrl}}" background-size="cover"></image> <text class="userinfo-nickname">{{props.userInfo.data.nickName}}</text> </view> <view class="userorder"> <view class="userorder-title">{{props.userInfo.title}}</view> <view class="userorder-list"> <view class="orderinfo" wx:key="{{index}}" wx:for-index="key" wx:for="{{props.userInfo.order}}"> <view class="orderinfo-date">发车时间:{{item.trainDate}}</view> <view class="orderinfo-traininfo">车次信息:{{item.trainCode+' '+item.startCity+'——'+item.endCity+' '+item.seatName}}</view> <view class="orderinfo-date">预约时间:{{item.created}}</view> </view> </view> </view> </view>
六、参考文档 Mobx文档 http://cn.mobx.js.org/ 小程序文档 https://mp.weixin.qq.com/debug/wxadoc/dev/index.html 小程序案例——火车票查询|余票预约通知 https://github.com/Vizn/wechat_ticket |