微信小程序开发学习6(基础加强之使用npm包和全局数据共享及分包【Tab底栏案例改进】)

微信小程序开发学习6(基础加强之使用npm包和全局数据共享及分包)

1、使用npm包

小程序对npm包的支持

目前,小程序中已经支持使用p安装第三方包,从而来提高小程序的开发效率。但是,在小程序中使用npm包有如下3个限制:

  1. 不支持依赖于Node.js内置库的包
  2. 不支持依赖于浏览器内置对象的包
  3. 不支持依赖于C++插件的包

虽然npm上的包有千千万万,当是可以为小程序使用的却不多

1.1、Vant Weapp

Vant Weapp是有赞前端团队开源的一套小程序UI组件库,助力开发者快速搭建小程序应用。它所使用的是MT开源许可协议,对商业使用比较友好。

官方参考文档如下:介绍 - Vant Weapp (youzan.github.io)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nJZvVTgT-1658322842026)(image/1、Vant Weapp.png)]

1.2、安装Vant组件库

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8IAuK9pE-1658322842027)(image/2、外部终端打开.png)]

初始化包管理配置文件

npm init -y

初始化成功会在项目的根目录中生成一个package.json文件

1.2.1、通过npm安装(建议指定版本为@1.3.3)

npm i @vant/[email protected] -S --production

1.2.2、构建nmp包

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OiYaB2zk-1658322842027)(image/3、构建npm.png)]

目前开发者工具是没有使用npm模块选项了,构建npm包之后直接使用

1.2.3、修改app.json文件

将 app.json 中的 "style": "v2" 去除,小程序的新版基础组件强行加上了许多样式,难以覆盖,不关闭将造成部分组件样式混乱。

1.3、使用Vant组件

安装完Vant组件库之后,可以在app.json的usingComponents节点中引入需要的组件,即可在wxml中直接使用组件。示例代码如下:

"usingComponents": {
    
    
    "van-button": "@vant/weapp/button/index"
}

在Vant Weapp官网对应的组件库中可以看到具体的引入信息

引入组件之后就可以在全局访问了

<van-button type="default">默认按钮</van-button>
<van-button type="primary">主要按钮</van-button>
<van-button type="info">信息按钮</van-button>
<van-button type="warning">警告按钮</van-button>
<van-button type="danger">危险按钮</van-button>

1.4、定制全局主题样式

Vant Weapp使用css变量来实现定制主题,基本用法参考:使用 CSS 自定义属性(变量) - CSS(层叠样式表) | MDN (mozilla.org)

基本用法

1.4.1、定义变量

element声明是有作用域的

element {
    
    
  --main-bg-color: brown;
}

1.4.2、使用变量

使用一个局部变量时用 var() 函数包裹以表示一个合法的属性值:

element {
    
    
  background-color: var(--main-bg-color);
}

在小程序中定义主题样式

1.4.3、在app.json中写入css变量,即可对全局生效

在小程序中page就是项目的根节点

page{
    
    
  /*定制警告按钮的背景颜色和边框颜色*/
  --button-danger-backgrount-color:#C00000;
  --button-danger-border-color:#C60000;
}

关于定制变量的名称可以查看官方给出的进行修改:vant-weapp/var.less at dev · youzan/vant-weapp (github.com)

1.5、API Promise化

默认情况下,小程序官方提供的异步API都是基于回调函数实现的

缺点:容易造成回调地狱的问题,代码可读性、维护性差

API Promise化,指的是通过额外的配置,将官方提供的、基于回调函数的异步API,升级改造为基于Promise的异步APl,从而提高代码的可读性、维护性,避免回调地狱的问题。

1.5.1、实现API Promise化

在小程序中,实现API Promise化主要依赖于miniprogram-api-promise这个第三方的npm包,安装和使用如下

npm install --save [email protected]

每安装一个包都要进行构建

构建之前先将miniprogram_npm文件夹删除再构建

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vqSCNm6d-1658322842028)(image/4、miniprogram-api-promise@1.0.4.png)]

在小程序入口文件中(app.js)只需要调用一次promisifyAll()方法,即可实现异步API的promise化

// app.js
// 导入miniprogram-api-promise
import {
    
    promisifyAll} from 'miniprogram-api-promise'
// 定义成员
const wxp = wx.p = {
    
    }
// 调用promisifyAll方法实现promise化【wx被promise化后会挂载到wxp对象】
// 后面就可以使用wx.p来调用promise化后的API了
promisifyAll(wx,wxp)

1.5.2、调用Promise化的异步API

按钮调用

<van-button type="primary" bindtap="getInfo">主要按钮</van-button>

在对应页面.js文件中定义方法

async getInfo(){
    
    
    const {
    
    data:res} = await wx.p.request({
    
    
      url:'https://applet-base-api-t.itheima.net/api/get',
      method:'get',
      data:{
    
    
        naem:'zs',
        age:20
      }
    })
    console.log(res)
}

2、全局数据共享

全局数据共享(又叫做:状态管理)是为了解决组件之间数据共享的问题。

开发中常用的全局数据共享方案有:Vuex、Redux、MobX等。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ytLi7pV4-1658322842028)(image/5、全局数据共享.png)]

2.1、小程序中的全局数据共享方法

在小程序中,可以使用mobx-miniprogram配合mobx-miniprogram-bindings实现全局数据共享

  • mobx-miniprogram用来创建Store实例对象
  • mobx-miniprogram-bindings用来把Store中的共享数据或方法,绑定到组件或页面中使用

2.2、安装Mobx相关的包

在项目中允许如下命令,安装Mobx相关的包

npm install --save [email protected] [email protected]

记住删除miniprogram_npm目录后再构建npm

2.3、创建Stor实例

在项目的根目录中创建一个store的文件夹存放store.js文件

// 在这个js文件中,专门来创建Store的实例对象
import {
    
    observable,action} from 'mobx-miniprogram'
// 导出供外界使用
export const store = observable({
    
    
	// 声明共享数据
	NumA:1,
	NumB:2,
	// 计算属性的值,get只读属性不允许修改
	get sum(){
    
    
		return this.NumA + this.NumB
	},
	// 我们不可以在外界直接修改共享的数据,必须通过调用方法的方式进行修改
	// actions方法,用来修改store中的数据
	updateNum1:action(function(step){
    
    
		this.NumA += step
	}),
	updateNum2:action(function(step){
    
    
		this.NumB += step
	})
})

2.4、将Store中的成员绑定到页面中

// pages/message/message.js
// 导入指定的方法
import {
    
    createStoreBindings} from 'mobx-miniprogram-bindings'
import {
    
    store} from '../../store/store'
Page({
    
    

    /**
     * 页面的初始数据
     */
    data: {
    
    

    },
    /**
    * 点击按钮调用+1或-1
    */
    btnHandler1(e){
    
    
        console.log(e)
        this.updateNum1(e.target.dataset.step)
    },

    /**
     * 生命周期函数--监听页面加载
     */
    onLoad(options) {
    
    
        // 将需要的属性字段和方法绑定到当前页面的yhis
        this.storeBindings=createStoreBindings(this,{
    
    
            // 数据源
            store,
            // 需要绑定的数据和计算值绑定到页面
            fields:['NumA','NumB','sum'],
            // 需要绑定的方法
            actions:['updateNum1','updateNum2']
        })
    },
    /**
     * 生命周期函数--监听页面卸载
     */
    onUnload() {
    
    
        this.storeBindings.destroyStoreBindings()
    }
})

绑定之后就可以在页面中进行调用了

<!--pages/message/message.wxml-->
<text>numA的值:{
   
   {NumA}}</text>
<view>numB的值:{
   
   {NumB}}</view> 
<view>{
   
   {NumA}} + {
   
   {NumB}} = {
   
   {sum}}</view>
<view></view>
<van-button type="primary" bindtap="btnHandler1" data-step="{
     
     {1}}">NumA+1</van-button>
<van-button type="danger" bindtap="btnHandler1" data-step="{
     
     {-1}}">NumA-1</van-button>

2.5、将Store中的成员绑定到组件中

2.5.1、在项目根目录中创建一个numbers组件

2.5.2、在项目的app.json中注册组件

"usingComponents": {
    
    
    "my-numbers": "./components/numbers/numbers"
}

2.5.3、在页面中使用自定义组件

<my-numbers></my-numbers>

2.5.4、在组件的js文件中绑定store的成员

// components/numbers/numbers.js
// 按需导入
import {
    
    storeBindingsBehavior} from 'mobx-miniprogram-bindings'
// 导入实例
import {
    
    store} from '../../store/store'
Component({
    
    
    // 实现自动绑定
    behaviors:[storeBindingsBehavior],
    // 绑定关系
    storeBindings:{
    
    
        // 数据源
        store,
        fields:{
    
    
            // 映射的字段:store里的字段被映射
            NumA:'NumA',
            NumB:'NumB',
            sum:'sum'
        },
        actions:{
    
    
            updateNum2:'updateNum2'
        }
    }
})

2.5.5、在组件中如何使用Store中的成员

<!--components/numbers/numbers.wxml-->
<text>numA的值:{
   
   {NumA}}</text>
<view>numB的值:{
   
   {NumB}}</view> 
<view>{
   
   {NumA}} + {
   
   {NumB}} = {
   
   {sum}}</view>
<view></view>
<van-button type="primary" bindtap="btnHandler2" data-step="{
     
     {1}}">numB+1</van-button>
<van-button type="danger" bindtap="btnHandler2" data-step="{
     
     {-1}}">NumB-1</van-button>

在组件的js文件中的methods节点创建上面的方法

/**
 * 组件的方法列表
 */
methods: {
    
    
    btnHandler2(e){
    
    
        // 调用映射过来的updateNum2方法
        this.updateNum2(e.target.dataset.step)
    }
}

效果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6PTGxiG3-1658322842029)(image/6、案例效果‘.png)]

3、分包

分包指的是把一个完整的小程序项目,安装需求划分为不同的子包,在构建时打包成不同的分包,用户在实用时按需进行加载

好处:

  1. 可以优化小程序首次启动的下载时间
  2. 在多人团队共同开发时可以更好的解耦协作

3.1、分包前后对比

分包前

分包前,小程序项目中所有的页面和资源都被打包到了一起,导致整个项目体积过大,影响小程序首次启动的下载时间。

分包后

分包后,小程序项目由1个主包+多个分包组成

  1. 主包:一般只包含项目的启动页面TabBar页面,以及所有分包所需要用到的一些公共资源
  2. 分包:只包含和当前分包有关的页面和私有资源

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lbi9tAcs-1658322842029)(image/7、分包.png)]

3.2、分包的加载规则

  1. 在小程序启动时,默认回下载主包启动主包页面

    tabBar页面需要放到主包中

  2. 当用户进入分包内某个页面时,客户端回把对应的分包进行下载,下载后再进行展示

    非tabbar页面可以按照功能的不同,划分为不同的分包之后,进行按需下载

3.3、分包的体积限制

  1. 整个小程序所有分包大小不超过16M(主包+所有分包)
  2. 单个分包/主包大小不可以超过2M

3.4、在项目里面实现分包

在项目的app.json文件中通过subPackages节点进行添加分包的路径,与pages节点同级关系

{
    
    
  "pages":[
    "pages/index/index",
    "pages/message/message",
    "pages/contact/contact"
  ],
  "subPackages": [
    {
    
    
      "root": "pkgA", // 存放分包的根目录
       "name": "p1", // 给分包起别名
        
      "pages": [ // 当前分包下的所有页面的相对路径
        "pages/cat/cat",
        "pages/dog/dog"
      ]
    },
    {
    
    
      "root": "pkgB",
      "name": "p2",
      "pages": [
        "pages/apple/apple",
        "pages/dog2/dog2"
      ]
    }
  ]
}

输入路径之后保存开发者工具就会自动的生成分包的文件信息

3.5、查看主包和分包的体积

在小程序详情的基本信息页面即可看到

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AvsOj5Y1-1658322842030)(image/8、体积.png)]

3.6、打包的基本准则

  1. 小程序按subpackages的配置进行分包,subpackages之外的目录将被打包到主包中
  2. 主包也可以有自己的pages(即最外层的pages字段)
  3. tabBar页面必须在主页面内
  4. 分包之间不能相互嵌套

3.7、引用原则

  1. 主包无法引用分包内的私有资源
  2. 分包之间不能相互引用私有资源
  3. 分包可以引用主包内的公共资源

独立分包

独立分包本质上也是分包,只不过它比较特殊,可以独立于主包和其他分包而独立运行

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5n3WeiPz-1658322842031)(image/9、独立分包.png)]

1、独立分包和普通分包的区别

是否依赖于主包才能运行

  1. 普通分包必须依赖于主包才能运行
  2. 独立分包可以在不下载主包的情况下独立运行

2、独立分包的应用场景

开发者可以按需,将某些具有一定功能独立性的页面配置到独立分包中:

  1. 当小程序从普通分包页面启动时,需要先下载主包
  2. 而独立分包不依赖主包即可运行,可以很大程度上提示分包页面的启动速度

注意:一个小程序中可以有多个独立分包

3、独立分包的建立

在app.json文件中定义,于普通分包的区别就是多了一个independent属性来绝定为独立分包

"subPackages": [
    {
    
    
      "root": "pkgB",
      "name": "p2",
      "pages": [
        "pages/apple/apple",
        "pages/dog2/dog2"
      ],
      "independent": true
    }
  ]
}

4、引用原则

独立分包和普通分包以及主包之间是相互隔离的,不能相互引用彼此的资源

  1. 主包无法引用独立分包内的私有资源
  2. 独立分包之间,不能i相互引用私有资源
  3. 独立分包和普通分包之间不能相互引用私有资源
  4. 特别注意:独立分包中不能引用主包内的公共资源

分包预下载

分包预下载指的是:在进入小程序的某个页面时,由框架自动预下载可能需要用到的分包,从而提示进入后续分包页面时的启动速度

1、配置分包预下载

预下载分包的行为,会在进入指定的页面时触发

在app.json中,使用preloadRule节点定义分包的预下载规则,代码如下

// 分包预下载的规则节点
"preloadRule": {
    
    
    // 指定进入指定页面进行预下载路径
    "pages/contact/contact": {
    
    
       // 表示在指定的网络模式下进行预下载【all不限网络、wifi为默认】
      "network": "all",
       // 表示进入页面后,预下载哪一个分包【通过分包的root或name都可以进行指定】 
      "packages": ["pkgA"]
    }
  }

2、分包预下载的限制

同一个分包中的页面享有共同的预下载大小限额2M

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TBHh1IyO-1658322842031)(image/10、分包预下载限制.png)]

4、案例-自定义TabBar

用到的知识点:

  1. 自定义组件
  2. vant组件库
  3. Mobx数据共享
  4. 组件样式隔离
  5. 组件数据监听器
  6. 组件的behaviors
  7. Vant样式覆盖

4.1、实现步骤

自定义tabBar分为3答步骤,分别是:

  1. 配置信息

    • app.json 中的 tabBar 项指定 custom 字段,同时其余 tabBar 相关配置也补充完整。
    • 所有 tab 页的 json 里需声明 usingComponents 项,也可以在 app.json 全局开启。

    对应list数组必须要保留,不然可能底版本的不能兼容

    "tabBar": {
          
          
    "custom": true,
    "list": [
      {
          
          
        "pagePath": "pages/index/index",
        "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"
      }
    ]
    }
    
  2. 添加tabBar代码文件

    在项目的根目录中创建custom-tab-bar文件夹,命名必须是这一个不能改,并且在文件里面创建一个index组件名称也是不能改的

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-T5dbPHap-1658322842032)(image/11、custom-tab-bar.png)]

    当index组件创建完成后我们原有的tabBar中的list数组就会被该index.wxml页面结构所覆盖

  3. 编写tabBar代码

    推荐使用want weapp中的tabbar组件

    需要使用相关的组件就需要引入对应的组件信息到项目

    <van-tabbar active="{
           
           { active }}" bind:change="onChange">
      <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>
    
    

    index.js中的tabBar数据【是组件.js文件】

    /**
     * 组件的初始数据
     */
    data: {
          
          
        active: 0,
        list: [
          {
          
          
            "pagePath": "pages/index/index",
            "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",
             info:0
          },
          {
          
          
            "pagePath": "pages/contact/contact",
            "text": "我的",
            "iconPath": "/images/tabs/contact.png",
            "selectedIconPath": "/images/tabs/contact-active.png"
          }
        ]
    }
    
  4. 渲染tabBar上的数字徽标

    在<van-tabbar-item>标签上通过info='0'属性可以指定生成的徽标数,但是不是每一个tabbar都会用到,可以在定义的data数据源中的tabbar需要的选项后面添加info:0字段来完成指定的选项添加

    徽标的溢出的解决

    在没有解决之前图片的底部是由一个margin-bottom样式撑着导致放大后会看到徽标溢出

    在自定义组件中使用 Vant Weapp 组件时,需开启styleIsolation: 'shared'选项【在组件.js文件中】

    // custom-tab-bar/index.js
    Component({
          
          
        options:{
          
          
            // 启用覆盖样式
            styleIsolation:'shared'
        }
    })
    

    覆盖的样式如下

    /* custom-tab-bar/index.wxss */
    .van-tabbar-item {
          
          
    	--tabbar-item-margin-bottom:0
    }
    
  5. 在组件中使用Mobx

    // custom-tab-bar/index.js
    import {
          
          selectedIconPath} from 'mobx-miniprogram-bindings'
    import {
          
          store} from '../store/store'
    Component({
          
          
        behaviors:[selectedIconPath],
        storeBindings:{
          
          
            store,
            fields:{
          
          
                sum:'sum'
            },
            actions:{
          
          }
        },
        /**
         * 数据监听器
         */
        observers:{
          
          
            'sum':function(str){
          
          
                // 修改tabBar中的消息数据
               this.setData({
          
          
                   'list[1].info':str
               })
            }
        }
    })
    
  6. 效果图

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9op2xqdY-1658322842033)(image/12、徽章效果.png)]

  7. 实现tabBar栏的切换

    在监听tabBar栏上进行切换事件跳转页面

    onChange(event) {
          
          
        this.setData({
          
           active: event.detail });
        // 获取到地址进行跳转
        wx.switchTab({
          
          
          url: this.data.list[event.detail].pagePath,
        })
    }
    
  8. 解决点击TabBar栏的索引问题

    原因:当点击其他的tabbar栏的时候被选中的标识不一定会出现在点击的那个tab栏上

    1. 将切换的索引active放到公共的组件store中存储

    2. 同时也要将index.wxml页面所使用的active进行移除

    3. store.js公共文件中声明一个方法专门修改索引的

      updateActiveTabBarIndex:action(function(index){
              
              
          this.activeTabBarIndex = index
      })
      
    4. index.js文件中映射store中的新添加字段和修改方法

      storeBindings:{
              
              
          store,
          fields:{
              
              
              sum:'sum',
              active:'activeTabBarIndex' // 映射的索引
          },
          actions:{
              
              
              updateActive:'updateActiveTabBarIndex' // 修改索引的方法
          }
      }
      

      在页面被切换的时候调用修改索引方法

      onChange(event) {
              
              
          this.setData({
              
               active: event.detail });
          // 修改切换的索引
          this.updateActive(event.detail)
          // 获取到地址进行跳转
          wx.switchTab({
              
              
            url: this.data.list[event.detail].pagePath,
          })
      }
      
    5. 在页面的标签中添加action属性

      <van-tabbar active="{
              
              {active}}" bind:change="onChange"></<van-tabbar>
      
    6. 修改tabBar选中项的文本颜色

      在标签上通过active-color="#13A7A0"属性进行修改

      <van-tabbar active="{
               
               {active}}" bind:change="onChange" active-color="#13A7A0"/>
      

可以参考官方文档手册:自定义 tabBar | 微信开放文档 (qq.com)

猜你喜欢

转载自blog.csdn.net/baidu_39378193/article/details/125900864