(一)MobX store 中的数据和页面逻辑层数据没同步
(1)出错原因:觉得createStoreBindinds把store.carpoolOrder绑定给了this.carpoolOrder。用户触发openMap()后就可以更改store中的数据,同时更改了this.carpoolOrder。事实是前者实现了,后者没有。
(2)真相
虽然 MobX 通过反应式机制管理数据更新,但在某些情况下,看到 this.carpoolOrder
没有立即更新,原因包括:
-
异步更新: MobX 的数据更新是异步的。在
openMap
的success
回调中,当调用this.setField
和this.setStartPositionField
更新 store 的字段时,更新并不会立即反映到this.carpoolOrder
。因此,紧接着在同一个回调中访问this.carpoolOrder
可能会得到旧值。 -
批量更新: MobX 会批量处理状态更新,以优化性能。在某些情况下,多个更新操作可能会被一起处理,导致在某些时候访问
this.carpoolOrder
时,它并没有及时反映出最新的状态。
(3)验证
把store.carpoolOrder再给到this.carpoolOrder:
控制台打印可以看到carpoolOrder是有值了:
(二) 页面逻辑层和视图层数据不一致
(1)问题:那为什么页面数据和this.carpoolOrder不一致呢?
<view class="start-point-container" style="margin-top: 200px;">
<view>你将从
<view class="select-point" bindtap="openMap"> {{carpoolOrder.startPoint || '选择起点'}} </view> 上车
</view>
<view class="selected-location">
<view>选中的地点:</view>
<view>名称:{{carpoolOrder1.startPoint || '未选择'}}</view>
<view>地址:{{carpoolOrder1.startPosition.address || '未选择'}}</view>
<view>经度:{{carpoolOrder1.startPosition.lng || '未选择'}}</view>
<view>纬度:{{carpoolOrder1.startPosition.lat || '未选择'}}</view>
</view>
</view>
(2)真相:data
是小程序的视图层与逻辑层之间的唯一桥梁。页面上的 wxml
只能访问 data
中的字段。虽然 createStoreBindings
会在 MobX store 中的数据变化时更新逻辑层中的字段(不是说刚刚,刚刚是手动更新的逻辑层this.carpoolOrder),但它不会自动更新 data
,也就不会自动触发视图的重新渲染。因为微信小程序的视图层更新机制依赖于 this.setData。
(3)验证:用this.setData更新视图层的数据
可以看到数据已经全部渲染成功了:
附示例代码:
页面js
import { createStoreBindings } from 'mobx-miniprogram-bindings';
import { store } from '../../store/store';
Page({
data: {
carpoolOrder: {}
},
onLoad() {
// 使用 createStoreBindings 绑定 store 中的数据到页面
this.storeBindings = createStoreBindings(this, {
store,
fields: ['carpoolOrder'],
actions: ['setField','setStartPositionField']
});
},
onUnload() {
// 页面卸载时解除绑定
this.storeBindings.destroyStoreBindings();
},
// 选择起点位置
openMap() {
wx.chooseLocation({
success: (res) => {
console.log('Location chosen:', res);
// 更新 startPosition 的 startPoint,address, lng, lat
this.setField('startPoint', res.name);
this.setStartPositionField('address', res.address);
this.setStartPositionField('lng', res.longitude);
this.setStartPositionField('lat', res.latitude);
this.setData({
carpoolOrder: store.carpoolOrder
});
},
fail: (err) => {
console.error('Failed to choose location:', err);
}
});
}
});
页面wxml
<view class="start-point-container" style="margin-top: 200px;">
<view>你将从
<view class="select-point" bindtap="openMap"> {{carpoolOrder.startPoint || '选择起点'}} </view> 上车
</view>
<view class="selected-location">
<view>选中的地点:</view>
<view>名称:{{carpoolOrder.startPoint || '未选择'}}</view>
<view>地址:{{carpoolOrder.startPosition.address || '未选择'}}</view>
<view>经度:{{carpoolOrder.startPosition.lng || '未选择'}}</view>
<view>纬度:{{carpoolOrder.startPosition.lat || '未选择'}}</view>
</view>
</view>
store.js
// store.js
import { observable } from 'mobx-miniprogram';
export const store = observable({
carpoolOrder: {
members: [],
startPoint: null,
startPosition:{
address:'',
lng:'',
lat:'',
},
endPoint: null,
endPosition:{
address:'',
lng:'',
lat:'',
},
status: '',
time: ''
},
// 更新拼车订单的整个数据对象
setCarpoolOrder(newOrder) {
this.carpoolOrder = newOrder;
this.saveCarpoolOrder(); // 持久化
},
// 更新拼车订单中指定字段的数据
setField(key, value) {
this.carpoolOrder[key] = value;
this.saveCarpoolOrder(); // 持久化
},
// 更新 startPosition 中的单个字段
setStartPositionField(field, value) {
this.carpoolOrder.startPosition[field] = value;
this.saveCarpoolOrder(); // 持久化
},
// 保存拼车订单到本地存储
saveCarpoolOrder() {
wx.setStorageSync('carpoolOrder', this.carpoolOrder);
},
// 从本地存储加载拼车订单
loadCarpoolOrder() {
const savedOrder = wx.getStorageSync('carpoolOrder');
if (savedOrder) {
this.carpoolOrder = savedOrder;
}
}
});