微信小程序数据同步太难?MobX让跨组件通信像呼吸一样简单

278 阅读4分钟

微信小程序文章推荐: 微信小程序必备开发技能总结(不断更新)

引言:小程序开发中的数据同步困境

在微信小程序开发过程中,数据同步和跨组件通信一直是开发者面临的重大挑战。传统的开发方式中,我们常常会遇到这样的场景:

  • 用户在一个页面修改了个人资料,需要在其他三个页面实时更新显示
  • 购物车组件的数据变更需要同步到商品列表、底部栏和结算页面
  • 全局主题色的切换需要立即反映在所有组件上

使用小程序原生的setData和事件机制来实现这些功能,往往会导致代码变得臃肿复杂,维护成本急剧上升。每次数据变更都需要手动触发事件、层层传递回调,稍有不慎就会出现数据不一致的问题。这也就是为什么我们需要使用Mobx的原因, 它能让小程序的数据同步变得简单直观,就像呼吸一样自然。

一、MobX简介:响应式编程的利器

1. MobX的核心概念

MobX是一个简单、可扩展的响应式状态管理库,其核心思想是"任何源自应用状态的东西都应该自动获得"。它包含三个基本概念:

  • Observable(可观察状态):被MobX跟踪的状态
  • Action(动作):修改状态的方法
  • Reaction(反应):状态变化时的自动响应

2. MobX与Redux的对比

相比于Redux的"单一store、不可变状态、纯函数reducer"理念,MobX采用了更灵活的方式:

特性MobXRedux
编程范式面向对象/响应式编程函数式编程
状态可变性直接修改不可变,总是返回新状态
样板代码极少较多(action, reducer等)
学习曲线平缓陡峭
适合场景中小型应用,快速开发大型应用,需要严格的状态管理
调试工具MobX DevToolsRedux DevTools

对于微信小程序开发而言,MobX的优势尤为明显:

  • 更少的样板代码
  • 更直观的API设计
  • 自动化的依赖追踪
  • 更高的开发效率

二、在微信小程序中集成MobX

这里我们以一个模拟登录退出的简单案例来掌握MobX的使用。

1. 安装依赖

npm install mobx-miniprogram mobx-miniprogram-bindings --save

安装完成后在开发者工具中点击工具 -> 构建npm, 确保依赖正确构建,构建完成之后会有一个miniprogram_npm的文件夹。

image.png

2. 创建全局Store

在项目根目录下创建一个store文件夹,store文件夹下面创建user.js文件。编写代码如下

import { observable, action } from 'mobx-miniprogram'

export const userStore = observable({
    // 存储用户信息
    userInfo: null, 
    // 存储登录状态
    get isLogin () {
        return !!this.isLogin
    },
    // 模拟登录
    login: action(function (userData) {
        this.userInfo = userData
    }),
    // 退出登录
    loginOut: action(function () {
        this.userInfo === null
    }) 
})


3. 在页面中绑定Store

3.1 登录页面

pages下面创建login 页面

login.js 代码如下:

import { createStoreBindings } from 'mobx-miniprogram-bindings'
import { userStore } from '../../store/user'
Page({

    /**
     * 页面的初始数据
     */
    data: {
        username: '',
        password: ''
    },
    updateName (e) {
        this.data.username = e.detail.value
    },
    onLoad () {
        this.store = createStoreBindings(this, {
            store: userStore,
            fields: ['userInfo', 'isLogin'],
            actions: ['login', 'logut']
        })

        if (this.data.isLogin) {
            wx.navigateTo({
              url: '/pages/index/index',
            })
        }
    },
    onUnload() {
        // 卸载页面后销毁掉对应的store, 避免内存泄漏
        this.store.destroyStoreBindings()
    },
    clickLogin (e) {
        const info = this.data
        this.login({
            name: info.username,
            email: info.username + '@qq.com'
        })
        wx.navigateTo({
            url: '/pages/index/index',
        })
    }
})

在这个文件中:

  • 从mobx-miniprogram-bindings 中导入了createStoreBindings方法
  • createStoreBindings 创建于页面this的关系
  • fields 列出计算属性和数据需要映射到页面的this上的data属性对应关系
  • actions 列出store 中actions中的对应关系

login.wxml

<view class="login-wrap">
    <view>
        <input 
            type="text" 
            placeholder="请输入用户名" 
            value="{{ userName }}" 
            bindinput="updateName"
        />
    </view>
    <view>
        <input 
            type="password" 
            placeholder="请输入用户密码" 
            bindinput="updatePassword" 
        />
    </view>
    <button type="primary" bindtap="clickLogin">登录</button>
</view>

login.wxss

.login-wrap {
    padding-left: 20rpx;
    padding-right: 20rpx;
}
.login-wrap input {
    border: 1px solid #ddd;
    margin: 20rpx 0;
    height: 80rpx;
    padding-left: 20rpx;
}

3.2 首页

index.js


import { createStoreBindings } from 'mobx-miniprogram-bindings'
import { userStore } from '../../store/user'
Page({
    data: {
    },
    onLoad() {
        this.store = createStoreBindings(this, {
            store: userStore,
            fields: ['userInfo', 'isLogin'],
            actions: ['logOut']
        })
        setTimeout(() => {
            if (!this.data.isLogin) {
                wx.navigateTo({
                  url: '/pages/login/login',
                })
            }
        })
    }
})

index.wxml

<!--index.wxml-->
<view class="container">
    <view>
        您的用户名是: {{ userInfo.name}}
    </view>
    <view>
        您的邮箱是: {{ userInfo.email}}
    </view>
    <button type="primary" bindtap="logOut">退出登录</button>
</view>

index.wxss

.container view{
    margin-bottom: 40rpx;
}

运行效果:

login.gif

三、总结

本篇先阐述了传统开发中数据转递的问题,然后引出Mobox,通过一个登录的案例介绍了Mobox的用法和特性。 感谢你的收看,若你对小程序开发感兴趣可以关注uni-app,小程序知识储备