一、微信小程序自身的應用狀態是怎樣定義的呢?
-
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
|