讓微信小程式頁面之間的通訊不在變得困難
阿新 • • 發佈:2019-06-03
一個開始
小程式開發者總會碰到各種頁面之間的通訊問題,實現方式也五花八門,比如...
場景還原
首先這是一個電商小程式。
有這樣一個需求:
- 首頁某個地方要展示購物車商品數量。
- 當我在其他頁面加購了商品,首頁數量重新整理。
實現方式
- 方式一:onShow直接請求介面
Page({ onShow() { // ...一些邏輯 // 後端請求新的購物車數量 this.requestCartNum(); } })
不足: 每次onShow都要請求介面,浪費資源。
- 方式二:globalData儲存購物車數量,onShow中做重新整理
// 主頁.js Page({ onShow() { // 在globalData獲取到購物車資料 let num = globalData.cartNum; if (num !== this.data.cartNum) { this.setData({ cartNum: num, }); } } }); // 加購頁.js Page({ // 加購後改變globalData的值 cartAdd(num) { globalData.cartNum = globalData.cartNum + num; } })
- 方式三:加購後獲取首頁例項,呼叫首頁方法
// 首頁.js Page({ onCartAdd(num) { this.setData({ cartNum: this.data.cartNum + num, }); }, }); // 加購頁.js Page({ onCartAdd(num) { // 加購後獲取到首頁的例項,呼叫首頁onCartAdd方法 let pages = getCurrentPages(); let curPage = pages[0]; curPage.onCartAdd(num); } })
不足:不確定能不能準確拿到首頁的例項,如果換做其他頁面就很難複用
- 方法四:事件訂閱與釋出
// 首頁.js Page({ onLoad() { // 首頁監聽事件 this.$bus.on('cart_add', (num) => { this.setData({ cartNum: this.data.cartNum + num, }) }) } }) // 加購頁.js Page({ // 加購成功後觸發cart_add事件 onCartAdd(num) { this.$bus.emit('cart_add', num); } })
此方法用事件系統,訂閱釋出模式去做的處理。
以上幾種方法中最優解決方案是方法四,利用事件的訂閱與釋出,邏輯清晰相容性好。但是都不可避免的不足是:每一個需要動態顯示購物數量的頁面都需要新增相同的邏輯程式碼。
狀態管理方案
單頁應用中最常用的就是元件之間的通訊,由此誕生了不同的狀態儲存方案: react用redux, vue用vuex。他們的思路都是類似的。都有一個核心 store
儲存著一切要管理的狀態。
那麼,其他框架可以,小程式也可以。以redux為例,實現一套簡單的狀態管理方案。
wxdux的實現
使用前提:有redux基礎
wxdux 類似與redux,以action來描述觸發的行為,reducer來描述state的變化。
1. 小程式入口中註冊
註冊store並新增到globalData中去
import {createStore} from './wxdux/index'; import reducer from './reducer'; const store = createStore(reducer); App({ globalData: { store, }, });
2. reducer實現
寫法與redux類似,功能也類似。
const userReducer = (state = {}, action) => { // ... } const postReducer = (state = [], action) => { // ... }; const reducers = { user: userReducer, posts: postReducer, }; export default reducers;
3. 頁面中使用wxdux
connect方法會將小程式頁面例項與wxdux連線起來,必須提供$useState方法,該方法接收state,返回該頁面所需要的state
import {connect} from './wxdux/index'; Page(connect({ data: { sex: '男', }, onLoad() { // ... }, $useState(state) { return { name: state.name, }, }, }))
4. wxml中使用name
<view>{{name}}</view>
5. 觸發store更新
使用dispatch方法,該方法接收一個物件作為引數,該物件必須包含type欄位表示action的型別,wxdux會根據此action更新state並且重新整理所有使用name的檢視
import {dispatch} from './wxdux/index'; Page(connect({ // 某點選事件觸發,更新姓名為“張三” onClick() { const updateName = { type: 'update_name', name: '張三' }; dispatch(updateName); } }))
最後
github