微信小程序miniprogram-computed:计算属性computed和监听器watch存储获取store: mobx-miniprogram、mobx-miniprogram-bindings

一、mobx-miniprogram 介绍

随着项目的业务逻辑越来越复杂,组件和页面间通信就会变得非常复杂。例如:有些状态需要在多个页面间进行同步使用,一个地方发生变更,所有使用的地方都需要发生改变,这时候如果使用前面的数据通信方案进行传递数据,给管理和维护将存在很大的问题。
为了方便进行页面、组件之间数据的传递,小程序官方提供了一个扩展工具库:mobx-miniprogram
mobx-miniprogram 时针对小程序开发的一个简单、高效、轻量级状态管理库,它基于 Mobx 状态管理框架实现。
使用 mobx-miniprogram 定义管理的状态时响应式的,当状态一旦它改变,所有关联组件都会自动更新相对应的数据
通过该扩展工具库,开发者可以很方便地在小程序中全局共享地状态,并自动更新视图组件,从而提升小程序地开发效率

二、注意

在使用 mobx-miniprogram 需要安装两个包:mox-miniprogram 和 mobx-miniprogram-bindings

  1. mobx-miniprogram 地作用:创建 Store 对象,用于存储应用地数据
  2. mobx-miniprogram-bindings 的作用:将状态和组件、页面进行绑定关联,从而在组件和页面中操作数据
npm install mobx-miniprogram mobx-miniprogram-bindings

三、官方文档

mobx-miniprogram 官方文档
mobx-miniprogram-bindings 官方文档

四、创建Store 对象、使用 Store数据

如果需要创建Store对象需要使用mobx-miniprogram,因此需要先熟悉mobx-miniprogram三个核心概念:

  1. observable:用于创建一个被检测的对象,对象的属性就是应用的状态(state),这些状态会被转换成响应式数据。
  2. action:用于修改状态(state)的方法,需要使用 action 函数显示的声明创建。
  3. computed:根据已有状态(state)生成的新值.计算属性是一个方法,在方法前面必须加上get修饰符。
mobx-miniprogram 详细的使用步骤如下:
  1. 在项目的根目录下创建 store 文件夹,然后在该文件夹下新建 numStore.js
  2. 在 /store/index.js 导入 observable、action 方法
import {observable,action} from 'mobx-miniprogram'
  1. 使用 observable 方法需要接受一个 store 对象,存储应用的状态
import { observable, action } from 'mobx-miniprogram'
export const numStore = observable({
    num1: 1,
    num2: 2,
    // 定义 action 方法,用来修改状态
    update: action(function() {
        // 在方法中如果需要获取状态,可以使用this进行获取
        this.num1 += 1;
        this.num2 += 2;
    }),
    // 计算数学 computed
    // 是根据已有的状态,产生新的状态
    // 计算属性前面需要使用 get 修饰符进行修饰
    get sum() {
        return this.num1 + this.num2
    }
})
  1. 在组件中使用数据

如果需要 Page 或 Component 中对共享的数据进行读取、更新操作,需要使用 mobx-miniprogram-bindings
mobx-miniprogram-bindings 的作用就是将 Store 和页面或组件进行绑定关联
如果需要在组件中使用状态,需要 mobx-miniprogram-bindings 库中导入 ComponentWithStore 方法
使用时:需要将 Component 方法 替换成 ComponentWithStore 方法,原本组件配置也需要写到该方法中。
在替换以后,就会新增一个 storeBindings 配置项,配置项常用的属性有以下三个:

  1. store:指定要绑定 Store 对象
  2. fields:指定需要绑定的 data 字段
  3. actions:指定需要映射的 actions 方法

注意事项:
导入的数据会同步到组件的 data 中
导入的方法会同步到组件的 methods 中

示例:
1.新建全局组件 custom01
2. 在 custom01.js 文件中
// 如果需要在组件中使用 Store 中的数据以及方法
// 需要从 mobx-miniprogram-bindings 里面引入 
import { ComponentWithStore } from 'mobx-miniprogram-bindings'
// 导入当前组件需要使用的 Store 对象
import { numStore } from '../../stores/numStore'
// 需要使用 ComponentWithStore 方法将 Component 方法进行替换
ComponentWithStore({
    // 用来配置当前组件需要与那些 Store 进行关联
    storeBindings: {
        store: numStore,
        fields: ['num1', 'num2', 'sum'],
        actions: ['update']
    }
})

注意: 在从Store 对象中引入数据和方法以后 如果是数据,会被注入到 data 对象中 如果是方法,会被注入到 methods 对象中

3.打开 custom01.wxml中
<view>{{num1}}+{{num2}}={{sum}}</view>
<button type="warn" plain bindtap="update">更新 Store 中的数据</button>
4.页面中使用 Store 数据方式

第一种方式:

Component 方法用于创建自定义组件。
小程序的页面也可以视为自定义组件,因此页面也可以使用 Component 方法进行构建,从而实现复杂的页面逻辑开发。
如果我们使用了Component 方法来构建页面,那么页面中如果想使用 Store 中的数据,使用方式和组件的使用方式是一样的。

  1. 从 mobx-miniprogram-bindings 库中导入 ComponetWithStore 方法
  2. 将 Component 方法 替换成 ComponentWithStore 方法
  3. 然后配置 storeBindings 从 Store 中映射数据和方法即可

打开 cart.js 把 Page 改成 ComponentWithStore

// 如果需要在组件中使用 Store 中的数据以及方法
// 需要从 mobx-miniprogram-bindings 里面引入 
import { ComponentWithStore } from 'mobx-miniprogram-bindings'
// 导入当前组件需要使用的 Store 对象
import { numStore } from '../../stores/numStore'
// 需要使用 ComponentWithStore 方法将 Component 方法进行替换
ComponentWithStore({
    // 用来配置当前组件需要与那些 Store 进行关联
    storeBindings: {
        store: numStore,
        fields: ['num1', 'num2', 'sum'],
        actions: ['update']
    }
})

打开 cart.wxml 文件 直接使用

<view>{{num1}}+{{num2}}={{sum}}</view>
<button type="warn" plain bindtap="update">更新 Store 中的数据</button>

第二种方式:

需要使用 mobx-miniprogram-bindings 提供的 BehaviorWithStore 方法来和 Store 建立关联。
小程序的 behavior 方法是一种代码复用的方式,可以将一些通用的逻辑和方法提取出来,然后在多个组件中复用,从而减少代码冗余,提高代码的可维护性,在页面中也可以使用 behaviors 配置项
使用方式如下:

  1. 新建 behavior 文件,从 mobx-miniprogram-bindings 库中导入 BehaviorWithStore 方法
  2. 在 BehaviorWithStore 方法中配置 storeBindings 配置项从 Store 中映射数据和方法
  3. 在 Page 方法中导入创建的 behavior ,然后配置 behavior 属性,并使用导入的 behavior

在cart 文件夹下新建文件 【behaviors.js】

// 小程序页面如果想使用 Store 对象中的数据或方法
import { BehaviorWithStore } from 'mobx-miniprogram-bindings'
import { numStore } from '../../stores/numStore'
// BehaviorWithStore 方法的作用:
// 让页面和Stroe 对象建立关联
export const cartBehavior = BehaviorWithStore({
    storeBindings: {
        store: numStore,
        fields: ["num1", "num2", "sum"],
        actions: ["update"]
    }
})

打开 cart.js 文件

// 需要先导入 提取的
import { cartBehavior } from './behaviors'
Page({
    // 使用 behaviors 配置项 提取的 behavior 
    behaviors: [cartBehavior]
})

打开 cart.wxml 文件

<view>{{num1}}+{{num2}}={{sum}}</view>
<button type="warn" plain bindtap="update">更新 Store 中的数据</button>

五、fields、actions 对象写法

filds 和 actions 有两种写法:数组写法 和 对象写法 首推 数组写法

数组写法
  storeBindings: {
        store: numStore,
        fields: ['num1', 'num2', 'sum'],
        actions: ['update']
    }
对象写法
fields 数据有两种写法 :映射形式和函数形式

映射形式:需要指定 data 中哪些字段 来源于 store ,以及在 store 中的名字是什么

fields: {      
	num1: 'num1',
	num2: 'num2',
	sum: 'sum'
 },

函数形式:key: data 中哪些字段 来源于 store ;value: 函数,函数内部需要返回对应 store 数据的值

fields: {    
	num1: () => numStore.num1,
	num2: () => numStore.num2,
	sum: () => numStore.sum,
 },
如果将 actions 改为对象写法 actions 只有一种写法

指定模板中使用的哪些方法来源于 store,并且 store 中的名字是什么

actions: {
	update: 'update'
 }

六、绑定多个 store 以及命名空间

如果一个组件或者页面需要绑定多个 Store 对象
需要将 storeBindings 配置项改造成一个数组
数组每一项是一个个要绑定的 Store 对象

注意:

如果 一个组件或页面需要绑定多个 Store 对象
从 Store 对象中引入了相同的数据或者方法
这时候代码就会出现异常
解决办法:

  1. 第一种解决方案:将其中一个 store 的fields 以及actions 改成对象方式
  2. 第二种解决方案:添加命名空间
    如果是数据存在冲突(存在相同的数据或方法),添加命名空间没有问题
    但是如果是方法冲突(存在相同的数据或方法),依然需要使用对象的方式来改造
    在添加命名空间以后,如果需要访问数据,需要加上空间的名字才可以
// 如果需要在组件中使用 Store 中的数据以及方法
// 需要从 mobx-miniprogram-bindings 里面引入 
import { ComponentWithStore } from 'mobx-miniprogram-bindings'
// 导入当前组件需要使用的 Store 对象
import { numStore } from '../../stores/numStore'
import { cloneStore } from "../../stores/cloneStore"
// 需要使用 ComponentWithStore 方法将 Component 方法进行替换
ComponentWithStore({
    storeBindings: [{
            store: numStore,
            fields: ['num1', 'num2', 'sum'],
            actions: ['update']
        },
        {
            namespace: "cloneStore",
            store: cloneStore,
            fields: ['num1', 'num2'],
            actions: {
                update1: "update"
            }
        },
    ]
})

在添加命名空间以后,如果需要访问数据,需要加上命名空间的名字才可以

<view>{{cloneStore.num1}}+{{cloneStore.num2}}={{cloneStore.sum}}</view>
<button type="warn" plain bindtap="update1">更新 Store 中的数据</button>

七、miniprogram-computed

小程序框架没有提供计算属性相关的 api ,但是官方为开发者提供了扩展工具库 miniprogram-computed
该工具库提供了两个功能:

1.计算属性 computed
2.监听器 watch

npm install --save miniprogram-computed

计算属性:基于已有的数据产生新的数据
在使用 ComponentWidthComputed 方法构建组件以后
这时候,就可以新增两个配置项 computed 以及 watch 配置项

计算属性 computed

计算属性方法内部必须有返回值
在计算属性内部,不能使用this来获取 data 中的数据
如果想获取 data 中的数据,需要使用 形参
只要计算属性依赖的数据发生了变化,计算属性就会重新进行计算

// 需要使用导入的ComponentWithComputed 替换 Compoent 方法
import { ComponentWithComputed } from 'miniprogram-computed'
ComponentWithComputed({
    computed: {
        total(data) {
            return data.a + data.b
        }
    },
    data: {
        a: 1,
        b: 2
    }
})

计算属性 具有缓存特性
计算属性只执行一次,后续在使用的时候,返回的是第一次执行的结果
只要依赖的数据,没看发生改变,返回的始终是第一次执行的结果

监听器 watch

watch 数据监听器,用来监听数据是否发生了变化,在数据变化以后执行响应的逻辑

key: 需要监听的数据
value: 是回调函数,回调函数有个形参,形参是最新的、改变以后的数据

// 需要使用导入的ComponentWithComputed 替换 Compoent 方法
// 需要使用导入的ComponentWithComputed 替换 Compoent 方法
import { ComponentWithComputed } from 'miniprogram-computed'
ComponentWithComputed({
    computed: {
        total(data) {
            return data.a + data.b
        }
    },
    watch: {
        a: function(a) {
            console.log(a)
        },
        b: function(b) {
            console.log(b)
        }
    },
    data: {
        a: 1,
        b: 2
    },
    methods: {
        updateData() {
            this.setData({
                a: this.data.a + 1,
                b: this.data.b + 2
            })
        }
    }
})

watch简写方式

同时监听多个数据,数据与数据之间需要使用 ,进行分隔
在watch 内部监听到数据变化以后,就可以进行响应的逻辑

watch: {
        'a,b': function(a, b) {
            console.log(a, b)
        }
    },

八、Mobx 与 Computed 结合使用

两个框架扩展提供的 ComponentWithStore 与 ComponentWithComputed 方法无法结合使用。
如果需要在一个组件中既想使用 mobx-miniprogram-bindings 又想使用 miniprogram-computed

解决方案是:

  1. 使用旧版 API
  1. 使用兼容写法(推荐使用此方法)
  • 即要么使用 ComponentWithStore 方法构建组件,要么使用 ComponentWithComputed 方法构建组件
  • 如果使用了 ComponentWithStore 方法构建组件,计算属性写法使用旧版 API
  • 如果使用了 ComponentWithComputed 方法构建组件,Mobx 写法使用旧版 API

目前组件使用的是 ComponentWithComputed 进行构建
如果想和 stroe 对象建立关联、进行绑定
Mobx 需要使用旧版 API

// 从 mobx-miniprogram-bindings 里面引入 ComponentWithStore 方法
import { ComponentWithStore } from 'mobx-miniprogram-bindings'
// 导入当前组件需要使用的 Store 对象
import { numStore } from '../../stores/numStore'
// 如果使用 ComponentWidthStore 方法构建组件
// 计算属性扩展库需要使用旧版 API
// 导入计算属性 behavior 
const computedBehavior = require('miniprogram-computed').behavior
// 注册 behavior
ComponentWithStore({
    // 注册 behavior
    behaviors: [computedBehavior],
    computed: {
        total(data) {
            return data.a + data.b
        }
    },
    watch: {
        'a,b': function(a, b) {
            console.log(a, b)
        }
    },
    data: { a: 1, b: 2 },
    methods: {
        updateData() {
            this.setData({
                a: this.data.a + 1,
                b: this.data.b + 1
            })
        }
    },
    storeBindings: {
        store: numStore,
        fields: ['num1', 'num2', 'sum'],
        actions: ['update']
    }
})

<view>{{num1}} + {{num2}} = {{sum}} </view>
<button type="warn" plain bindtap="update">更新 Store 中的数据</button>
<view>{{a}}+{{b}}={{total}}</view>
<button type="primary" bindtap="updateData">更新数据</button>

反之:

import { ComponentWithComputed } from 'miniprogram-computed'
import { numStore } from '../../stores/numStore'
import { storeBindingsBehavior } from 'mobx-miniprogram-bindings'
ComponentWithComputed({
    behaviors: [storeBindingsBehavior],
    storeBindings: {
        store: numStore,
        fields: ['num1', 'num2', 'sum'],
        actions: ['update']
    },
    computed: {
        total(data) {
            return data.a + data.b
        }
    },
    methods: {
        updateData() {
            this.setData({
                a: this.data.a + 1,
                b: this.data.b + 1
            })
        }
    },
    data: {
        a: 1,
        b: 2
    }
})
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值