mobx-miniprogram小程序的数据传输
1.mobx-miniprogram介绍
小程序页面,组件之间的数据通信方案分别有以下几种
- 数据绑定:properties
- 获取组件实例:this.selectComponent()
- 事件绑定:this.triggerEvent()
- 获取应用实例:getApp()
- 页面间通信:EventChannel
- 事件总线:pubsub-js
在中小型项目中,使用这些数据通信方式已经能够满足我们项目的需求.
但是随着项目的业务逻辑越来越复杂,组件和页面间通信就会变的非常复杂.例如:有些状态需要在多个页面间进行同步使用,一个地方发生变更,所有使用的地方都需要发生改变,这时候如果使用前面的数据通信方案进行传递数据,给管理和维护将存在很大的问题.
为了方便进行页面,组件之间数据传递,小程序官方提供了一个扩展工具库:mobx-miniprogram
mobx-miniprogram 是针对微信小程序开发的一个简单,高效,轻量级状态管理库,它基于Mobx状态管理框架实现.
使用mobx-miniprogram 定义管理的状态是响应式的,当状态一旦它改变,所有关联组件都会自动更新相应的数据通过该扩展工具库,开发者可以很方便的在使用小程序中全局共享的状态,并自动更新视图组件,从而提升小程序的开发效率.
需要注意:在使用mobx-miniprogram需要安装两个包:mobx-miniprogram 和mobx-miniprogram-bindings
- mobx-miniprogram 的作用:创建 Store对象,用于存储应用的数据
- mobx-miniprogram-bindings 的作用:将状态和组件,页面进行绑定关联,从而在组件和页面中操作数据
安装:
npm install mobx-miniprogram mobx-miniprogram-bindings
2.创建 Store对象
如果需要创建Store对象需要使用mobx-miniprogram,因此需要先熟悉mobx-miniprogram单个核心概念:
- observable:用于创建一个被检测的对象,对象的属性就是应用的状态(state),这些状态会被转换成响应式数据.
- action:用于修改(state)的方法,需要使用action函数显式的声明创建.
- computed:根据已有状态(state)生成的新值.计算属性是一个方法,在方法前面必须加上get修饰符
2.1.mobx-miniprogram详细的使用步骤如下:
- 在项目的根目录下创建Store文件夹,然后在该文件夹下面新建index.js
- 在 /store/index.js 导入observable ,action方法
//observable:用于创建一个被检测的对象,对象的属性就是应用的状态(state),这些状态会被转化成响应式数据. //action:函数是用来显示的定义action方法, action方法是用来修改,更新状态import {observable ,action} form "mobx-miniprogram"
- 使用observable方法需要接受一个store对象,存储应用的状态
//开始创建Store对象export const numStore = observable({//对象的属性就是应用的状态numA:1,numB:2,//定义action方法,用来修饰状态update:action(function(){//在方法中如果需要获取状态,可以使用this进行获取.this.numA +=1,this.numB +=1})//计算属性 computed //是根据已有的状态产生新的状态//计算属性前面需要使用get修饰符进行修饰get sum(){//计算属性内部必须要有返回值return this.numA + this.numB}})
2.2.在组件中使用数据
如果使用Page或者Component 中对共享的数据进行读取,更新操作,需要使用mobx-miniprogram-bindings ,而mobx-miniprogram-bindings 的作用就是将Store和页面或组件进行绑定关联.
如果需要在组件中使用状态,需要mobx-miniprogram-bindings 库中导入ComponentWithStore方法.在使用时:需要将Component方法替换成ComponentWithStore方法,原本组件配置项也需要写到该方法中.
在替换以后,就会新增一个storeBingings配置项,配置项常用的属性有以下三个:
1.store:指定要绑定的store对象
2.fields:指定需要绑定的data字段
3.actions:指定需要映射的actions方法
注意事项:
导入的数据会同步到组件的data中
导入的方法会同步到组件的methods中
//1.创建一个组件//如果需要在组件中使用Store中的数据以及方法
//需要从mobx-miniprogram-bindings里面引入ComponentWithStore方法import { ComponentWithStore } form "../"//导入当前组件需要使用的Store对象
import { numstore } form "../../stores/numstore"2.需要将组件原有的Component直接替换成ComponentWithStoreComponentWithStore({//组件的属性列表properties:{}//用来配置当前组件需要与那些Store进行关联//注意事项:在从Store对象中引入数据和方法以后,如果是数据,属性会被注入到data对象中(也就相当于在data{}直接拥有了这个属性,如果在html中使用的话,可以直接使用了,不需要单独在data{}再写一次了),
如果是方法,会被注入到methods对象中(方法同属性)storeBindings:{//需要和那个进行关联store: numstore,//当前组件需要使用numstore中的那些数据fields:["numA","numB","sum"]//numstore对象中来映射引入那些方法actions:["update"]}})
2.3.在页面中使用数据-方式1
Component方法用于创建自定义的组件.
小程序的页面也可以视为自定义组件,因此页面也可以使用Component方法进行构建,从而实现复杂的页面逻辑开发.
如果我们使用Component方法来构建页面,那个页面中如果想使用 Store中的数据,使用方式和组件的使用方式是一样的
1.从mobx-miniprogram-bindings库中导入ComponentWithStore方法;
2.将Component方法替换成ComponentWithStore方法;
3.然后配置storeBingings从Store中映射数据和方法即可.
2.4.在页面中使用数据-方式2
如果不想使用Component方法构建页面.这时候需要使用mobx-miniprogram-bindings 提供BehaviorWithStore 方法来和Store 建立关联.
小程序的behavior 方法是一种代码复用的方式,可以将一些通用的逻辑和方法提取出来,然后在多个组件中复用,从而减少代码冗余,提高代码的可维护性.在页面中可以使用Behaviors配置.
使用方式如下:
- 新建behavior文件,从mobx-miniprogram-bindings库中导入BehaviorWithStore方法
- 在BehaviorWithStore 方法中配置storeBingings配置项从Store中映射数据和方法
- 在page方法中导入创建的behavior,然后配置behavior属性,并使用导入的behavior
//新建behavior.js文件//小程序如果想使用Store对象中的数据或者方法,就必须先导入//需要从mobx-miniprogram-bindings导入BehaviorWithStore方法
import { BehaviorWithStore } from "mobx-miniprogram-bindings"//调用
//BehaviorWithStore方法的作用:让页面和Store对象建立关联export const cartBehavior = BehaviorWithStore({storeBindings:{store: numstore,//当前页面需要跟那个store对象进行关联//当前页面需要从numstore中导入那些数据fields:["numA","numB","sum"]//numstore对象中来映射引入那些方法actions:["update"]}})
//在页面的js文件中如何使用创建的behaviorimport {carBehavior} form "./behavior"Page({//使用behavior配置项注册提取的behavior//同样的carBehavior的属性和方法就已经被注册进了data{}方法里面behaviors:[carBehavior]})
2.5.fields,actions对象写法
fields,actions有两种写法:数组或者对象.
如果fields写成对象方式,有两种写法:
1.映射形式:指定daya中那些字段来源于store以及他们在store中对应的名字.
例如{a:"numA",b:"numB"}
2.函数形式:指定data中每个字段的计算方法
例如{ a:()=>store.numA, b:()=>anotherStore.numB }
如果actions写成对象方式,只有两种写法:
1.映射形式:指定模块中调用的那些方法来源于store以及他们在store中对应的名字.
例如:{buttonTap:"update"}
2.6.绑定多个store以及命名空间
在实际开发中,一个页面或者组件可能会绑定多个store,这时候我们可以将storeBingings 改造成数组.数组中每一项就是要一个个绑定的store.
如果多个store中存在相同的数据,显示会出现异常.还可以通过namespace属性给当前store开启命名空间,在开启命名空间以后,访问数据的时候,需要加上namespace的名字才可以.
//新建behavior.js文件//小程序如果想使用Store对象中的数据或者方法,就必须先导入//需要从mobx-miniprogram-bindings导入BehaviorWithStore方法
import { BehaviorWithStore } from "mobx-miniprogram-bindings"import { numStore } from "../../stores/numstore"
import { cloneStore } from "../../stores/clonestore"//调用
//BehaviorWithStore方法的作用:让页面和Store对象建立关联export const cartBehavior = BehaviorWithStore({//如果一个组件或者页面需要绑定多个store对象,需要将storeBindings配置项改成一个数组//数组每一项是一个个要绑定的store对象storeBindings:[{store: numstore,//当前页面需要跟那个store对象进行关联//当前页面需要从numstore中导入那些数据fields:["numA","numB","sum"]//numstore对象中来映射引入那些方法actions:["update"]},//如果一个组件或者页面需要绑定多个store对象//从store对象中引入了相同的数据或者方法//这时候代码就会出现异常{store: cloneStore,//第一中解决方案:将fields以及actions改成对象方式//fields:["numA","numB","sum"]//actions:["update"]fields:{a:"numA",b:"numB",total:"sum"},actions:{updateDate:"update"},//第二中解决方案:添加命名空间 //如果是数据存在冲突(存在相同的数据或者方法),添加命名空间没有问题的//但是如果是方法冲突(存在相同的数据或者方法),依然需要使用对象的方式来改造//在添加命名空间以后,如果需要访问数据,需要加上命名空间的名字才可以//cloneStore. numAnamespace:"cloneStore",fields:["numA","numB","sum"]actions:{updateDate:"update"},}]})
3.miniprogram-computed
小程序框架没有提供计算属性相关的api,但是官方为开发者提供了拓展工具库miniprogram-computed
该工具库提供了两个功能:1.计算属性 computed 2.监听器 watch
3.1.计算属性 computed
如果需要在组件中使用计算属性功能,需要miniprogram-computed 库中导入ComponentWithComputed方法.在使用时:需要将Component方法替换成ComponentWithComputed方法,原本组件配置项也需要写到该方法中
在替换以后,就可以新增Computed以及watch配置项.
安装ComponentWithComputed,在安装以后,需要单击构建npm,进行本地构建
npm install miniprogram-computed
//在js文件中
//如果需要在组件中使用计算属性功能,需要导入ComponentWithComputed方法import {ComponentWithComputed} from "miniprogram-computed"//对组件进行替换,需要使用导入的方法ComponentWithComputed替换Component方法
ComponentWithComputed({//计算属性:基于已有的数据产生新的数据//在使用ComponentWithComputed方法构建以后,这个时候,就可以新增两个配置项Computed以及watch配置项 //组件的初始数据 data:{a:1,b:2 },//组件的方法列表methods:{},//组件的方法列表computed:{total(data){//计算属性必须有返回值,在计算属性内不能使用this来获取data中数据//如果想获取data中数据,需要使用形参//计算属性只执行一次,后续在使用的时候,返回的值是第一次执行的结果.//只要依赖的数据没有发生改变,返回的值始终之是第一次执行的结果 return data.a + data.b},}})
3.2.监听器 watch
在使用时:需要将Component方法替换成ComponentWithComputed方法,原本组件配置项也需要写到该方法中.在替换后,就可以新增 computed 以及 watch配置项.
//在js文件中
//如果需要在组件中使用计算属性功能,需要导入ComponentWithComputed方法import {ComponentWithComputed} from "miniprogram-computed"//对组件进行替换,需要使用导入的方法ComponentWithComputed替换Component方法
ComponentWithComputed({//计算属性:基于已有的数据产生新的数据//在使用ComponentWithComputed方法构建以后,这个时候,就可以新增两个配置项Computed以及watch配置项 //组件的初始数据 data:{a:1,b:2 },//组件的方法列表methods:{},//组件的方法列表computed:{total(data){//计算属性必须有返回值,在计算属性内不能使用this来获取data中数据//如果想获取data中数据,需要使用形参//计算属性只执行一次,后续在使用的时候,返回的值是第一次执行的结果.//只要依赖的数据没有发生改变,返回的值始终之是第一次执行的结果 //只要计算属性依赖的数据发生了变化,计算属性就会重新执行return data.a + data.b},},//watch 数据监听器,用来监听数据是否发生了变化,在数据变化以后执行相应的逻辑watch:{//key:需要监听的数据//value:是回调函数,回调函数有一个形参,形参是最新的,改变以后得数据a:function(a){},//同时监听多个数据,数据与数据之间需要使用逗号隔开"a,b":function(a,b){//在watch内部监听到数据变化以后,就可以来执行相应的逻辑},}})