【微信小程序】——Mobx全局数据共享和分包
全局数据共享
1. 全局数据共享介绍
全局数据共享即状态管理
,是为了解决组件之间数据共享的问题,将数据统一存到Store
仓库里,各组件都能直接访问仓库内的数据,避免了各组件间频繁的数据传递等问题。
类似的有Vue
中的Vuex
,Redux
,Mobx
等。
不使用Store
:
使用Store
:
2. 小程序中的全局数据共享方案
在小程序中,可使用mobx-miniprogram
配合mobx-miniprogram-bindings
实现全局数据共享。
mobx-miniprogram
:用来创建Store
实例对象mobx-miniprogram-bindings
:用来把Store
中的共享数据或方法,绑定到组件或页面中使用
3. 安装Mobx相关的包
npm install --save mobx-miniprogram mobx-miniprogram-bindings
注意:安装完成后记得重新构建npm
4. 创建Mobx中Store实例
项目根目录下创建store文件夹用于存放Mobx相关的JS文件
创建store.js用来创建store实例
store.js:
//在这个JS文件里,专门来创建Store的实例对象
import { action, observable } from 'mobx-miniprogram'
export const store = observable({
//数据字段
numA: 1,
numB: 2,
//计算属性:当numA或numB变化时,自动更新sum的值
get sum() {
return this.numA + this.numB
},
// actions 方法,用来修改store中的数据
updateNum1: action(function (step) {
this.numA += step
}),
updateNum2: action(function (step) {
this.numB += step
})
})
注意:
- 计算属性的值是==只读==的,不能也不需要对其进行手动修改
- ==直接修改store里的数据可能会带来危险==,所以一般在actions方法里修改store里的数据
5. 页面中使用Store成员
5.1 在页面的JS中写入以下代码:
// 页面的.js文件
import { createStoreBindings } from "mobx-miniprogram-bindings";
import { store } from "../../store/store";
Page({
/**
* 页面的初始数据
*/
data: {
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
this.storeBindings = createStoreBindings(this,{
store,
fields:['numA','numB','sum'],
actions:['updateNum1']
})
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload: function () {
this.storeBindings.destroyStoreBindings()
},
})
代码分析:
- 引入
mobx
的createStoreBindings
方法和我们创建的store
实例:
import { createStoreBindings } from "mobx-miniprogram-bindings";
import { store } from "../../store/store";
createStoreBindings
方法可以将Store
中的数据或方法绑定到我们的页面中
- 在页面加载时,绑定
Store
:
onLoad: function (options) {
this.storeBindings = createStoreBindings(this,{
store,
fields:['numA','numB','sum'],
actions:['updateNum1']
})
},
createStoreBindings
方法接收两个参数,一个是this
代表当前页面的实例,第二参数是配置对象,包含三个属性:
store
代表数据源fields
代表我们需要将哪些字段绑定到我们的页面中actions
代表我们需要将哪些方法绑定到我们的页面中
createStoreBindings
的调用有一个返回值,我们将这个返回值挂载到了当前页面上作为一个自定义属性storeBindings
而存在,这样我们就可以在页面卸载时利用storeBindings
来清理挂载的Store实例
- 在页面卸载时接触绑定的
Store
:
onUnload: function () {
this.storeBindings.destroyStoreBindings()
},
调用
destroyStoreBindings
方法即可进行清理Store
5.2 在页面上使用Store
数据
页面的.wxm
结构:
<view>
{{numA}} +{{numB}} = {{sum}}
<button type="primary" bindtap="btn1" data-step="{{1}}">numA+1</button>
<button type="primary" bindtap="btn1" data-step="{{-1}}">numA-1</button>
</view>
在页面的JS中添加按钮tap事件的处理函数:
btn1(e){
this.updateNum1(e.target.dataset.step)
}
6. 组件中使用Store成员
6.1 在组件的JS中写入以下代码:
// components/numbers/numbers.js
import {storeBindingsBehavior} from "mobx-miniprogram-bindings"
import {store} from '../../store/store'
Component({
//通过storeBindingsBehavior来实现自动绑定
behaviors:[storeBindingsBehavior],
storeBindings:{
//指定要绑定的Store
store,
fields:{
// 绑定字段的第1种方式
numA:()=>store.numA,
// 绑定字段的第2种方式
numB:(store)=>store.numB,
// 绑定字段的第3种方式
sum:'sum'
},
actions:{
updateNum2:'updateNum2'
}
},
/**
* 组件的属性列表
*/
properties: {
},
/**
* 组件的初始数据
*/
data: {
},
/**
* 组件的方法列表
*/
methods: {
}
})
6.2 在组件上使用Store
数据
组件的.wxm
结构:
{{numA}}+{{numB}}={{sum}}
<button type="primary" bindtap="Cbtn1" data-step="{{1}}">CnumA+1</button>
<button type="primary" bindtap="Cbtn1" data-step="{{-1}}">CnumA-1</button>
在组件JS中的methods
方法列表中加入添加按钮tap事件的处理函数:
Cbtn1(e){
this.updateNum2(e.target.dataset.step)
},
分包
1. 基础概念
-
什么是分包?
分包指的是把一个完整的小程序项目,按照需求划分为不同的之包,在构建时打包成不同的分包,用户在使用时按需进行加载。 -
分包的好处?
- 可以优化小程序首次启动的下载时间
- 在多团队共同开发时可以更好的解耦协作
-
分包前项目的构成
分包前,小程序项目中所有的页面和资源都被打包到了一起,导致整个项目体积过大,影响小程序首次启动的下载时间。
-
分包后项目的构成
分包后,小程序项目由1个主包+多个分包组成:- 主包:一般只包含项目的启动页面或TabBar页面、以及所有分包都需要用到的一些公共资源
- 分包:只包含和当前页面有关的页面和私有资源
-
分包的加载规则
- 在小程序启动时,默认会下载主包并启动主包内页面
- tabBar页面需要放到主包中
- 当用户进入分包内某个页面时,客户端会把对应的分包下载下来,下载完成后再进行展示
- 非tabBar页面可以按照功能的不同, 划分为不同的分包之后,进行按需下载
- 在小程序启动时,默认会下载主包并启动主包内页面
-
分包的体积限制
目前,小程序分包的大小有以下两个限制:- 整个小程序所有分包大小不超过==16M==(主包+所有分包)
- 单个分包/主包大小不能超过==2M==
2. 使用分包
- 配置方法
app.json中添加以下分包的配置,保存后会自动生成相应的文件:
//app.json
"subpackages": [
{
"root":"pkgA",
"pages": [
"pages/cat/cat",
"pages/dog/dog"
]
},
{
"root":"pkgB",
"pages": [
"pages/apple/apple"
]
}
],
- 查看分包的体积大小
- 打包原则
-
小程序会按
subpackages
的配置进行分包,subpackages
之外的目录将被打包到主包中 -
主包也可以有自己的
pages
(即最外层的pages
字段)"pages":[ "pages/home/home", "pages/message/message", "pages/contact/contact" ],
-
tabBar
页面必须在主包内
如上代码即是tabBar
页面的配置,配置到了主包的pages
里 -
分包之间不能互相嵌套
-
- 引用原则
- 主包 无法引用分包内的私有资源
- 分包之间不能相互引用私有资源
- 分包可以引用主包内的公共资源
3. 独立分包
-
什么是独立分包
独立分包本质上也是分包,只不过它比较特殊,可以独立于主包和其它分包而单独运行。
-
独立分包和普通分包的区别
最主要的区别:是否依赖于主包才能运行- 普通分包必须依赖于主包才能运行
必须先进入主包才能跳到普通分包
- 独立分包可以在不下载主包的情况下,独立运行
- 普通分包必须依赖于主包才能运行
-
独立分包的应用场景
开发者可以按需,将某些具有一定功能独立性的页面配置到独立分包中,原因如下:- 当小程序从普通的分包页面启动时,需要首先下载主包
- 而独立分包不依赖主包即可运行,可以很大程度上提升分包页面的启动速度
注意:一个小程序中可以有多个独立分包
-
独立分包的配置方法
独立分包的目录结构于普通分包一样,独立分包只需在JSON
配置中通过independent
进行声明://app.json //pkgB设置为独立分包 "subpackages": [ { "root":"pkgA", "name": "p1", "pages": [ "pages/cat/cat", "pages/dog/dog" ] }, { "root":"pkgB", "name": "p2", "pages": [ "pages/apple/apple" ], "independent": true } ],
-
独立分包的引用原则
独立分包和普通分包以及主包之间,是相互隔绝的,不能相互引用批次的资源!例如:- 主包无法引用独立分包内的私有资源
- 独立分包之间,不能相互引用私有资源
- 独立分包和普通分包之间,不能相互引用私有资源
- 特别注意:独立分包中不能引用主包内的公共资源
4. 分包预下载
分包预下载指的是:在进入小程序的某个页面时,由框架自动预下载可能需要的分包
,从而提升进入后续分包页面时的启动速度。
-
配置分包的预下载
预下载分包的行为,会在进入指定的页面时触发。在app.json
中,使用preloadRule
节点定义分包的预下载规则,示例代码如下:
"preloadRule": { "pages/contact/contact":{ "packages": ["p1"], "network": "all" } }, "subpackages": [ { "root":"pkgA", "name": "p1", "pages": [ "pages/cat/cat", "pages/dog/dog" ] }, { "root":"pkgB", "name": "p2", "pages": [ "pages/apple/apple" ], "independent": true } ],
上述代码配置的是打开
pages/contact/contact
页面时,在任意网络环境下都会预下载p1
分包。打开
pages/contact/contact
页面时查看调试器控制台会有正在预下载p1
和预下载成功的提示:
-
分包预下载的限制
同一个分包的页面享有共同的预下载大小限额2M,例如:
案例:自定义tabBar
1.案例效果
在此案例中,用到的主要知识点如下:
- 自定义组件
- Vant组件库
- MobX数据共享
- 组件样式隔离
- 组件数据监听器
- 组件的behaviors
- Vant 样式覆盖
2. 实现步骤
-
配置信息
在app.json
文件的tabBar
中添加"custom": true
同时保留list里的配置项:"tabBar": { "custom": true, "list": [{ "pagePath": "pages/home/home", "text": "首页", "iconPath": "/images/tabs/home.png", "selectedIconPath": "/images/tabs/home-active.png" },{ "pagePath": "pages/message/message", "text": "消息", "iconPath": "/images/tabs/message.png", "selectedIconPath": "/images/tabs/message-active.png" },{ "pagePath": "pages/contact/contact", "text": "联系我们", "iconPath": "/images/tabs/contact.png", "selectedIconPath": "/images/tabs/contact-active.png" }] },
-
添加tabBar代码文件
项目根目录创建custom-tab-bar
文件夹,然后右键此文件夹新建Component
,起名为index
此时页面底部显示:
表示添加tabBar代码文件和配置成功 -
编写tabBar代码
custom-tab-bar/index.wxml
:<!--使用vant的van-tabbar 组件--> <van-tabbar active="{{ active }}" bind:change="onChange" active-color="#13A7A0"> <van-tabbar-item wx:for="{{list}}" wx:key="index" info="{{item.info?item.info:''}}"> <image slot="icon" src="{{ item.iconPath }}" mode="aspectFit" style="width: 25px; height: 25px;" /> <image slot="icon-active" src="{{ item.selectedIconPath }}" mode="aspectFit" style="width: 25px; height: 25px;" /> {{item.text}} </van-tabbar-item> </van-tabbar>
custom-tab-bar/index.wxss
:/* 修改van-tabbar样式进行样式覆盖 */ .van-tabbar-item { --tabbar-item-margin-bottom:0; }
custom-tab-bar/index.js
:// custom-tab-bar/index.js import { storeBindingsBehavior } from "mobx-miniprogram-bindings" import { store } from '../store/store' Component({ //在自定义组件中使用 Vant Weapp 组件时,需开启styleIsolation: 'shared'才能进行样式覆盖 options: { styleIsolation: 'shared' }, //通过storeBindingsBehavior来实现自动绑定 behaviors: [storeBindingsBehavior], storeBindings: { //指定要绑定的Store store, fields: { sum: 'sum', active:'active' }, actions:{ changeActive:'changeActive' }, }, /** * 数据监听器 */ observers:{ "sum":function (val) { // 赋值操作 this.setData({ 'list[1].info':val }) } }, /** * 组件的属性列表 */ properties: { }, /** * 组件的初始数据 */ data: { list: [{ pagePath: "/pages/home/home", text: "首页", iconPath: "/images/tabs/home.png", selectedIconPath: "/images/tabs/home-active.png" }, { pagePath: "/pages/message/message", text: "消息", // 消息数量 info: 0, iconPath: "/images/tabs/message.png", selectedIconPath: "/images/tabs/message-active.png" }, { pagePath: "/pages/contact/contact", text: "联系我们", iconPath: "/images/tabs/contact.png", selectedIconPath: "/images/tabs/contact-active.png" }] }, /** * 组件的方法列表 */ methods: { onChange(event) { // event.detail为选中项索引 // 调用store里的修改tabBar选中项索引的函数 this.changeActive(event.detail) // 手动实现页面跳转 wx.switchTab({ url: this.data.list[event.detail].pagePath, }) }, } })
store/store.js
://在这个JS文件里,专门来创建Store的实例对象 import { action, observable } from 'mobx-miniprogram' export const store = observable({ //数据字段 numA: 1, numB: 2, // tabBar选中项索引 active: 0, //计算属性:当numA或numB变化时,自动更新sum的值 get sum() { return this.numA + this.numB }, // actions 方法,用来修改store中的数据 updateNum1: action(function (step) { this.numA += step }), updateNum2: action(function (step) { this.numB += step }), changeActive: action(function (index) { this.active = index }) })
详细步骤,可以参考小程序官方文档:
https://developers.weixin.qq.com/miniprogram/dev/framework/ability/custom-tabbar.html
- 点赞
- 收藏
- 关注作者
评论(0)