手把手教你在微信小程序使用Redux
來自知乎 凌空
首先挡篓,為什么要在微信小程序中使用Redux澜倦?小程序雖然主張輕量級應用料按,但也難免會有些復雜情況。在應對某些異步場景瞬内,以及多個打開著的頁面相互影響的情況下迷雪,你需要有一個數(shù)據(jù)流管理庫才能更好地縷清思路,增加項目的可維護性虫蝶。
舉個栗子:你在A頁面點一個按鈕會發(fā)送遠程請求章咧,同時轉跳到B頁面,遠程請求返回值在B頁面顯示能真。這個場景在B頁面加載時遠程請求并沒有結束赁严,此請求會在獲得返回值的同時響應到B頁面上。
因為在A頁面點按鈕時并不存在B頁面粉铐,所以無法在遠程請求的異步回調(diào)中用getCurrentPages()在B頁面setData疼约。如果用app對象下的全局變量周轉,手寫代碼監(jiān)聽變化蝙泼,在項目變大后會變得極其難維護程剥。而使用Redux就可以很好地適應這種場景。
下面我針對剛舉的例子一步一步來說說如何將Redux整合進小程序汤踏,在文章結尾有GitHub鏈接织鲸。先創(chuàng)一個項目,有沒有appId都行溪胶。
在創(chuàng)建完后會有一個默認的小項目搂擦,我們就基于這個來吧。獲取redux.min.js并放進目錄哗脖∑偬撸可以找cdn下載到本地扳还,也可以從redux官方repo里自己編譯,只有10kb左右橱夭。然后創(chuàng)建actions.js和reducers.js普办,目錄如下圖。
添加一個修改文字的action徘钥,以及一個reducer用來改變Store里文字的狀態(tài)
// actions.js
export const changeText = (text) => {
return { type: 'CHANGE_TEXT', text }
}
// reducers.js
export default {
myText(state = '', action) {
switch (action.type) {
case 'CHANGE_TEXT':
return action.text
default:
return state
}
}
}
app.js中初始化Store,并放在App實例里以方便調(diào)用
//app.js
import { createStore, combineReducers } from './lib/redux.min'
import reducers from './reducers'
const Store = createStore(combineReducers(reducers))
App({
Store,
onLaunch: function () {
// ...
在首頁index.wxml編輯下肢娘,添加一個按鈕呈础,并bindtap
<!--index.wxml-->
<view class="container">
<view bindtap="bindViewTap" class="userinfo">
<image class="userinfo-avatar" src="{{userInfo.avatarUrl}}" background-size="cover"></image>
<text class="userinfo-nickname">{{userInfo.nickName}}</text>
</view>
<view class="usermotto">
<button type="primary" bindtap="bindBtn">2秒后改變下一頁的文字</button>
</view>
</view>
修改index.js,在bindBtn里用setTimeout 2000的方式模擬異步遠程請求2秒后返回橱健,再dispatch action將下一頁的文字設為'new text'而钞。同時轉跳到下一頁。
//index.js
import { changeText } from '../../actions'
//獲取應用實例
const app = getApp()
const Store = app.Store
const dispatch = Store.dispatch
Page({
data: {
userInfo: {}
},
bindBtn() {
setTimeout(() => {
dispatch(changeText('new text'))
}, 2000)
wx.navigateTo({
url: '../logs/logs',
})
},
// ...
在logs.wxml里只放一個{{foo}}
<!--logs.wxml-->
<view class="container">
{{foo}}
</view>
這一步是重點拘荡,在logs.js里的onLoad訂閱Store并響應式刷新data臼节,在onUnload里取消訂閱以節(jié)省資源。生命周期的管理看需要珊皿,也可以在onShow里訂閱网缝,onHide里取消訂閱。
//logs.js
const app = getApp()
const Store = app.Store
const dispatch = Store.dispatch
Page({
data: {
foo: ''
},
onLoad() {
const updateDate = () => {
const foo = Store.getState().myText
this.setData({ foo })
}
updateDate();
this.unsubStore = Store.subscribe(() => updateDate())
},
onUnload() {
this.unsubStore()
}
})
我們可以看到蟋定,logs頁面foo變量的初始值是空String粉臊,當Redux Store里的myText變化后馬上觸發(fā)subscribe的回調(diào),并用setData設置本頁面變量驶兜。
我們來測試下扼仲,在首頁點擊綠色按鈕后,瞬間轉跳到下一頁抄淑,過兩秒后出現(xiàn)'new text'字樣
這就是一個最基本的在微信小程序使用Redux的方法了屠凶。更高級的用法比如再配合redux-thunk這樣的中間件使用,讓異步流程更清晰肆资。
GitHub Repo地址 https://github.com/lhz516/wechat-mina-redux-example
本文例子是用Redux底層API實現(xiàn)矗愧,另外還可以用高階函數(shù)綁定的方式實現(xiàn),比如這個庫 wechat-weapp-redux 迅耘,它是參照react-redux中Provider和connect的概念贱枣。但我還是推薦初學者用Redux底層API走一遍,因為目前在小程序用Redux高階函數(shù)綁定的思路還不夠成熟颤专,比如是否只在onLoad里subscribe store纽哥,在onUnload里unsubscribe store?如果想使用栖秕,得做好自己維護的準備春塌。
相關傳送門:Redux文檔