微信小程序学习笔记

也是黑马教程中学习的视频

入门

创建小程序

打开网站 https://mp.weixin.qq.com/进行注册。

获取AppID;

打开开发者工具:

  1. 代理方式推荐改为不适用任何代理,勾选后直连网络

  2. 选择新建项目,填写项目名称、目录和AppID,后端服务选择不适用云服务。

  3. 点击编译后,可以在左侧查看运行效果;也可以点击预览,然后用手机微信扫码查看

开发者文档可以点击帮助中开发者文档;设置中进行通用设置;

结构

pages:存放所有小程序的页面

utils: 存放工具性质的模块

app.js: 小程序项目的入口文件

app.json: 小程序项目的全局配置文件

app.wxss: 小程序项目的全局样式

project.config.json: 项目的配置文件

sitemap.json:用来配置小程序及其页面是否允许被微信索引

建议每个页面单独放在一个文件夹中

js文件:页面的脚本文件,存放页面的数据、事件处理函数等

json文件:当前页面的配置文件,配置窗口的外观、表现等

wxml文件:页面的模板结构文件

wxss文件:当前页面的样式表文件

JSON配置文件

项目根目录中的app.json

​ 小程序的所有页面路径、窗口外观、界面表现、底部tab等。

​ pages:所有页面的路径。

​ window:全局定义所有页面的背景色、文字等。

​ style:所使用的样式,v2是其中的一个较新版本

​ sitemapLocation:指明sitemap.json的位置。

**项目根目录中的project.config.json **

​ 小程序的开发工具 个性化设置

​ setting:和编译相关的配置(和详情中的本地设置一致)

​ projectname:项目名称(不等于小程序名称,小程序的名称在详情中查看)

​ appid:小程序的账号ID

**项目根目录中的sitemap.json **

​ 配置小程序页面是否允许微信索引

​ action:allow,允许索引;disallow,不允许索引(警告修改setting中checkSitMap为false可不再弹出)

每个页面文件夹中的json

​ 本页面中的窗口外观设置,覆盖全局配置(项目根目录中的app.json)。

​ 配置内容同项目根目录中的app.json的window中的字段。

新建小程序页面

​ app.json中 pages 中新增页面的存放路径 即可,工具自动创建对应页面。

修改小程序项目首页

​ 调整 app.json 中 pages 数组中页面路径的先后顺序即可,默认把排在第一位的页面当做首页进行渲染。

wxml

​ 类似于html,区别

  1. 标签名称不同
    1. html(div,span,img,a)
    2. wxml(view, text, image, navigator)
  2. 属性节点不同
    1. <a href="#">连接</a>
    2. <navigator url="/page/home/home"></navigator>
  3. 类似于vue中的模板语法
    1. 数据绑定
    2. 列表渲染
    3. 条件渲染

wxss

​ 类似于css,区别

  1. 新增rpx尺寸单位
    1. css需要手动进行像素单位换算
    2. wxss在低层支持rpx,在不同大小屏幕上会自动进行换算
  2. 提供了全局的样式和局部样式
    1. 如app.wxss和 页面中的 wxss
  3. wxss仅支持部分css选择器
    1. .class 和 #id
    2. element
    3. 并集选择器、后代选择器
    4. ::after 和 ::before 等伪类选择器

js逻辑交互

  1. app.js
    1. 小程序入口,调用app()函数启动整个小程序
  2. 页面的js
    1. 页面的入口文件,通过调用Page()函数来创建并运行界面
  3. 普通的js
    1. 普通的功能模块文件,用来封装公共函数和属性

宿主环境

概念

宿主环境是指程序运行所必须的依赖环境。例如:android和iOS是两个不同的宿主环境。

手机微信是小程序的宿主环境,基于微信完成功能。

小程序宿主环境包含的内容包括:

  1. 通信模型
  2. 运行机制
  3. 组件
  4. API

通信模型

通信主体

  1. 渲染层:wxml模板和wxss样式工作在渲染层
  2. 逻辑层:js脚本工作在逻辑层

通信模型分为两部分:

  1. 渲染层和逻辑层之间的通信:由微信客户端进行转发
  2. 逻辑层和第三方服务器之间的通信: 由微信客户端进行转发

运行机制

小程序启动过程

  1. 将小程序的代码包下载到本地
  2. 解析app.json全局配置文件
  3. 执行app.js小程序入口文件,调用App()创建小程序实例
  4. 渲染小程序首页
  5. 启动完成

页面渲染过程

  1. 加载解析页面的json配置文件
  2. 加载页面的wxml模板和wxss样式
  3. 执行页面的js文件,调用page()创建页面实例
  4. 渲染完成

组件

组件由宿主环境提供,共分为九类

  1. 视图容器

    1. view:视图区域组件,类似于div,实现页面布局效果
    2. scroll-view: 可滚动的视图区域;实现滚动列表的效果
    3. swiper和swiper-item:轮播图容器组件,和轮播图item组件
  2. 基础内容

    1. text:文本组件,类似于span
    2. rich-text:富文本
  3. 表单组件

  4. 导航组件

  5. 媒体组件

  6. map地图组件

  7. canvas画布组件

  8. 开放能力

  9. 无障碍访问

view

横向布局,类名使用container貌似有问题

<view class="container1">
	<view>A</view>
    <view>b</view>
    <view>c</view>
</view>

.container1 view{
    width:50px;
    height:50px;
    text-align:center;
    line-height:50px;
}
.container1 view:nth-child(1){
    background-color:lightgreen;
}
.container1 view:nth-child(2){
    background-color:lightskyblue;
}
.container1 view:nth-child(3){
    background-color:lightcoral;
}
.container1{
    display: flex;
    justify-content: space-around;
}

scroll-view

实现纵向滚动效果,横向滚动使用scroll-x

<scroll-view class="container1" scroll-y>
	<view>A</view>
    <view>b</view>
    <view>c</view>
</scroll-view>
.container1 view{
    width:100px;
    height:100px;
    text-align:center;
    line-height:100px;
}
.container1 view:nth-child(1){
    background-color:lightgreen;
}
.container1 view:nth-child(2){
    background-color:lightskyblue;
}
.container1 view:nth-child(3){
    background-color:lightcoral;
}
.container1{
	border: 1px solid red;
    height:120px;
    width:100px;
}

swiper和swiper-item

<swiper class="swiper-container" indicator-dots>
    <swiper-item>
        <view class="item">A</view>
    </swiper-item>
    <swiper-item>
        <view class="item">b</view>
    </swiper-item>
    <swiper-item>
        <view class="item">c</view>
    </swiper-item>
</swiper>
.swiper-container{
    height: 150px;
}
.item{
    height: 100%;
    line-height: 150px;
    text-align: center;
}

swiper-item:nth-child(1) .item{
    background-color: lightgreen;
}
swiper-item:nth-child(2) .item{
    background-color: lightskyblue;
}
swiper-item:nth-child(3) .item{
    background-color: lightcoral;
} 

组件常用属性:

  1. indicator-dots : 默认false,是否显示面板指示点
  2. indicator-color: 默认rgba(0,0,0,.3),指示点颜色
  3. indicator-active-color : 默认#000000,当前选中指示点颜色
  4. autoplay : 默认false,是否自动切换
  5. interval : 默认5000,自动切换间隔,单位ms
  6. circular: 默认false,是否采用衔接滑动

text

通过text的selectable属性,实现长按选中文本内容,只有text支持长按选中。

<view>
    手机号可以长按选中
	<text selectable>13131311313</text>
</view>

rich-text

通过组件的nodes属性节点,可以把html字符串渲染为对应的UI结构:

<rich-text nodes="<h1 style='color:red;'>标题</h1>"></rich-text>

button

按钮组件,通过open-type属性可以调用微信提供的各种功能(客服、转发、获取用户授权、获取用户信息等)

<button>黑色按钮</button>
<button type="primary">绿色按钮</button>
<button type="warn">红色按钮</button>

<button size="mini">小尺寸按钮</button>
<button type="primary" size="mini">绿色按钮</button>
<button type="warn" size="mini">红色按钮</button>

<button size="mini" plain>小尺寸镂空按钮</button>
<button type="primary" size="mini" plain>绿色按钮</button>
<button type="warn" size="mini" plain>红色按钮</button>

image

图片组件,默认宽度300px,高240px

<image></image>
<image src="/images/1.png"></image>
<image src="/images/1.png" mode="aspectFit"></image>
image{
    border:1px solid red;
}

image组件的mode属性用来指定图片的裁剪和缩放模式,常见属性如下:

  1. scaleToFill:缩放模式(默认值),不保持纵横比缩放图片,是图片的宽高完全拉伸到填满image元素
  2. aspectFit:缩放模式,保持纵横比缩放图片,使图片的长边完全能够显示出来,可以完整的显示图片
  3. aspectFill:缩放模式,保持纵横比缩放图片,只保证图片的短边完全显示,也就是图片只在一个方向完整。
  4. widthFix:缩放模式,image宽度不变,高度自动变化(image的高度),保持原图宽高比不变
  5. heightFix:缩放模式,image高度不变,宽度自动变化(image的宽度),保持原图宽高比不变

API

小程序的API是宿主环境提供的,包括获取用户信息、本地存储、支付功能等。

事件监听

特点:以on开头,用来监听某些事件的触发

举例:wx.onWindowResize(function callback)监听窗口尺寸的变化

wx可以理解为js中的window全局对象。

同步API

特点:以sync结尾

​ 同步API的执行结果,可以通过函数返回值直接获取,失败则抛出异常

举例:wx.setStorageSync(‘key’,‘value’)向本地存储写入内容。

异步API

特点:类似于ajax(option),需要通过success、fail、complete等接受调用结果

举例:wx.request()发起网络请求,通过success回调函数接收数据。

发布

上传代码:点击开发工具栏中的上传,写版本号和项目备注。

查看版本:小程序管理后台,管理,版本管理,开发版本中查看

提交审核

发布

二维码获取:小程序管理后台,设置,基本设置,小程序码和线下物料下载

基础

数据绑定

在data中定义数据

在页面对应的js中

Page({
    data:{
        info:'hello',
        imgsrc:'http://www.itheima.com/images/logo.png',
        randomNum:Math.random() * 10,
        randomNum2:Math.random().toFixed(2),
    }
})

在wxml中使用数据

mustache语法,插值表达式

动态绑定内容

<view>{{info}}</view>

动态绑定属性

<image src="{{imgsrc}}"></image>

三元运算,算数运行

<view>{{randomNum >= 5 ? '大于5' : '小于5'}}</view>
<view>{{randomNum * 100}}</view>

可以在调试工具的AppData中查看data中的数据。

data赋值

通过this.setData设置,通过this.data访问

Page({
    data:{
        count:0
    },
    changeCount(){
        this.setData({
            count:this.data.count + 1
        })
    }
})

事件绑定

事件是渲染层到逻辑层的通讯方式,可以通过事件将用户在渲染层发生的行为,反馈到逻辑层处理。

常用事件:

类型绑定方式事件描述
tapbindtap,bind:tap类似于点击事件,手指点完离开
inputbindinput文本框输入
changebindchange状态改变,如checkbox

当事件回调触发时,会收到一个事件对象event,他的属性如下

属性类型说明
typestring事件类型
timeStampinteger页面打开到触发事件所经过的毫秒数
targetobject触发事件的组件的一些属性值集合
currentTargetobject当前组件的一些属性值集合
detailobject额外的信息
touchesarray触摸事件,当前停留在屏幕中的触摸点信息的数组
changedTouchesarray触摸事件,当前变化的触摸点信息的数组

target是触发事件的源头组件,currentTarget是当前事件所绑定的组件。

<view bindtap="handle">
	<button>
        按钮
    </button>
</view>

此时如果按钮上有点击事件,view上进行事件监听,那么target指向的是按钮,currentTarget指向的是view。

以上点击事件处理函数如下:

Page({
    handle(e){
        console.log(e)
    }
})

传参

不能在绑定事件的同时为事件处理函数传递参数,即以下写完不合规

<button type="primary" bindtap="handle(123)">事件传参</button>

需要通过’data-'传参,如下进行:

<button type="primary" bindtap="handle" data-info="{{2}}">
    事件传参
</button>

最终,info会被解析为参数的名字,数字2被解析为参数值。2需要放在{{}}中,否则会被解析为字符串2.

Page({
    handle(event){
        console.log(event.target.dataset)
        console.log(event.target.dataset.info)
    }
})

获取参数时通过event.target.dataset获取,dataset是一个对象,包含了所有通过data-*传递过来的参数项;通过dataset可以访问具体参数的值。

bindinput

绑定事件

<input bindinput="handle"></input>

事件处理

handle(e){
    console.log(e.detail.value)
}

e.detail.value是变化后,文本框最新的值。

文本框和data之间的数据同步

<input value="{{msg}}" bindinput="handle"></input>
Page({
    data:{
        msg:'hello'
    },
    handle(e){
        this.setData({
            msg:e.detail.value
        })
    }
})

条件渲染

通过wx:if="{{condition}}"来判断是否需要渲染代码块。

也可以使用wx:elifwx:else进行判断

<view wx:if="{{condition}}">ok1</view>
<view wx:elif="{{condition2}}">ok2</view>
<view wx:else>okelse</view>

结合block

如果一次性控制多个组件的显示和隐藏,可以使用block标签上加wx:if控制。block并不是一个组件,只是一个包裹性容器,不会在页面中做任何渲染。(为啥不用view呢?只是少渲染一个view)

<block wx:if="{{condition}}">
	<view>view1</view>
    <view>view2</view>
</block>

hidden

可以直接使用hidden="{{condition}}"进行控制显示隐藏。

<block hidden="{{condition}}">
	<view>view1</view>
    <view>view2</view>
</block>

不同:

  1. 运行方式
    1. wx:if 以动态创建和移除元素的方式控制 显示 隐藏
    2. hidden 以切换样式的方式(display:none/block),控制 显示 隐藏
  2. 建议
    1. 切换频繁,建议使用hidden
    2. 控制条件复杂,可以使用wx:if搭配wx:elif、wx:else

列表渲染

wx:for

​ 通过wx:for可以根据指定的数组,循环渲染重复的组件结构,如下:

<view wx:for="{{array1}}">
	索引:{{index}} 当前项是:{{item}}
</view>
Page({
  data:{
      array1 :["apple","banana"]
  }  
})

手动指定索引和当前项的变量名

修改index和item的变量名,可以使用其他名称指代

<view wx:for="{{array1}}" wx:for-index="idx" wx:for-item="itm">
	索引:{{idx}} 当前项是:{{itm}}
</view>

key

建议指定唯一key值,提高渲染效率

Page({
  data:{
      array1 :[
      	{id:1,name:'h'},
        {id:2,name:'e'},
        {id:3,name:'l'},
      ]
  }  
})
<view wx:for="{{array1}}" wx:key="id">
	索引:{{index}} 当前项是:{{item}}
</view>

没有key时 可以使用index作为key值

进阶

wxss

相较于css,扩展了 rpx 尺寸 和 @import ;也有一些选择器和样式不可使用。
rpx,解决小程序尺寸适配问题,rpx将屏幕横向上分为750份,rpx自动进行单位换算。一般建议iphone6作为视觉参考,1rpx=0.5px。
@import,后接需要导入的外联样式表的相对路径,用分号表示语句结束,如@import "common.wxss";,common.wxss在当前路径下,在wxss中使用。
全局样式,定义在app.wxss页面样式,作用于所有页面。
局部样式,定义在 页面.wxss 的样式,只作用于当前页面。局部样式会覆盖全局样式,只有局部页面样式权重大于等于全局样式才会覆盖。

全局配置

根目录中的app.json文件。

  1. pages, 记录当前小程序页面的存放路径
  2. window,全局设置窗口的外观
  3. tabBar,底部tabBar的效果
  4. style,是否启用新版的组件样式,值如‘v2’

window节点常用配置:

  1. navigationBarTitleText:导航栏标题文本
  2. navigationBarBackgroundColor:导航栏背景颜色,只支持"#121212"格式
  3. navigationBarTextStyle:导航栏标题文本颜色,只支持“white”和“black”
  4. enablePullDownRefresh:全局开启下拉刷新,true;会作用于每个页面,效果可能在开发工具中表现的有差异。
  5. backgroundColor:下拉刷新时的背景颜色,只能是"#121212"格式
  6. backgroundTextStyle:下拉刷新时的loading样式,小圆点样式,只能时light和dark。
  7. onReachBottomDistance:上拉触底的距离,默认距离50px,一般不更改。

tabBar

用于实现多页面切换,分为顶部tabBar和底部tabBar。
只能配置做少2个,最多5个;当渲染顶部tabBar,只显示文本。
在这里插入图片描述

  1. backgroundColor:背景色
  2. selectedIconPath:选中时的图片路径
  3. borderStyle:边框的颜色
  4. iconPath:未选中时的图片路径
  5. selectedColor:文字选中时的颜色
  6. color:文字未选中的颜色

app.json中tabBar节点配置项

  • position:bottom或者top
  • borderColor:边框的颜色
  • color:文字未选中的颜色
  • selectedColor:文字选中时的颜色
  • backgroundColor:背景色
  • list:必选,tab页列表,大于等于2个,小于等于五个

其中list项对象包括的配置选项如下:

  • pagePath: 必填,页面路径,同Pages中的内容
  • text: tab显示的文本呢
  • iconPath: 未选中时的图片路径
  • selectedIconPath:选中时的图片路径

注意:tabBar涉及到的页面必须放在pages数组中的前面。

页面配置

页面下的 .json文件,对单独页面窗口外观进行配置。
如,增加节点 navigationBarBackgroundColor:"#ff0000",则对当前页面导航栏进行了修改。
节点内容同app.json中window下各个键:navigationBarTitleTextnavigationBarBackgroundColornavigationBarTextStyleenablePullDownRefreshbackgroundColorbackgroundTextStyleonReachBottomDistance

网络数据请求

限制:

  1. 只能请求https类型的接口
  2. 必须将接口的域名添加到信任列表,(可以在开发工具中的详情➡项目配置➡域名信息 中查看 request合法域名)
  3. 所以地址必须时域名,不可以时ip的格式

配置合法域名:
登录微信小程序管理后台➡开发➡开发配置➡服务器域名➡需改request合法域名。

get请求

使用wx.request()方法

wx.request({
	url:'https://www.escook.cn/api/get',
	method:'GET',
	data:{
		name:'zs',
		age:'30'
	},
	success:(res)=>{
		console.log(res);
	}
})

post请求

使用wx.request()方法

wx.request({
	url:'https://www.escook.cn/api/post',
	method:'POST',
	data:{
		name:'zs',
		age:'30'
	},
	success:(res)=>{
		console.log(res);
	}
})

在页面加载时请求数据

可以在页面的 onLoad 中进行请求。

onLoad:function(options){
	this.getData();//页面中的方法
}

跳过request合法请求

可以在开发者工具中临时开启(详情➡本地设置) 开发环境不校验请求域名、TLS版本及https证书跳过域名校验。
只能在开发调试中使用。

跨域和ajax

  1. 小程序中不存在跨域的问题。
  2. ajax依赖于浏览器的XMLHttpRequest,但是小程序不是浏览器,所以只能叫做发起网络数据请求。

页面导航

即页面跳转

  1. 声明式导航:通过点击 <navigator> 实现条状。
  2. 编程时导航:调用api,

导航到tabBar页面(声明式)

需要指定url 和 open-type 属性,其中

  • url 表示要跳转到的页面地址,必须是 / 开头
  • open-type 表示跳转的方式,必须为 switchTab
    如:
<navigator url="pages/message/message" open-type="switchTab">导航到消息页面</navigator>

导航到非tabBar页面(声明式)

  • url 表示要跳转到的页面地址,必须是 / 开头
  • open-type 表示跳转的方式,必须为 navigate(此属性可以省略,效果相同)
    如:
<navigator url="pages/message/message" open-type="navigate">导航到非tab面</navigator>

后退导航(声明式)

  • delta值必须是数字,表示要后退的层级,默认为1,表示后退一步。
  • open-type 为 navigateBack,表示后退导航

导航到tabBar页面(编程式)

调用 wx.switchTab(Object object) 方法,可以跳转到tabBar,其中object属性:

  1. url 字符串,需要跳转的tabBar路径,路径不能带参数
  2. success 函数,成功的回调
  3. fail 函数,失败的回调
  4. complete 函数,完成的回调
wx.switchTab({
	url:'/pages/message/message'
})

导航到非tabBar页面(编程式)

调用 wx.navigateTo(Object object) 方法,可以跳转到非tabBar,其中object属性:

  1. url 字符串,需要跳转的非tabBar路径,路径不能带参数
  2. success 函数,成功的回调
  3. fail 函数,失败的回调
  4. complete 函数,完成的回调
wx.navigateTo({
	url:'/pages/message/message'
})

后退导航(编程式)

调用navigateBack,返回上一页面或多级页面,可选参数如下:

  1. delta字符串,表示要后退的层级,大于现有页面则返回首页
  2. success 函数,成功的回调
  3. fail 函数,失败的回调
  4. complete 函数,调用结束完成返回的回调

wx.navigateBack()默认返回上一页吗。

导航传参(声明式)

url路径后面可以携带参数:

  • 参数与路径之间使用?分割
  • 参数键与参数值用=相连
  • 不用参数用&分割
<navigator url="/pages/info/info?name=tom&age=30">跳转</navigator>

可以再模拟器左下角的页面参数查看。

导航传参(编程式)

调用wx.navigateTo(Object object)跳转时,可以携带参数,如下

wx.navigateTo({
	url:"pages/info/info?name=ls&age=32"
})

接受导航传参

在onLoad中直接获取(在options),假设存储到data中的query:

onLoad:function(options){
	console.log(options)
	this.setData({
		query:options
	})
}

在这里插入图片描述

下拉刷新和上拉触底

启用下拉刷新

  1. 全局开启,app.json ➡ window ➡ enablePullDownRefresh 设置true
  2. 局部开启,页面json ➡ enablePullDownRefresh 设置true(推荐)

下拉窗口样式

全局或者页面json中

  1. backgroundColor:背景颜色 16进制格式
  2. backgroundTextStyle:loading的样式,dark 或者light

监听下拉刷新事件

在页面.js 中 onPullDownRefresh() 函数中监听。

onPullDownRefresh:function(){
	//todo
	console.log("下拉刷新")
}

停止下拉刷新效果

通过wx.stopPullDownRefresh 实现:

onPullDownRefresh:function(){
	//todo
	console.log("下拉刷新")
	wx.stopPullDownRefresh()
}

监听上拉触底

在页面的js文件中,通过 onReachBottom 函数监听:

onReachBottom:function(){
	//todo
	console.log("上拉触底")
}

例子:

<view wx:for="{{colorList}}" wx:key="index" class="num-item" sytle="background-color:rgba({{item}})">{{item}}</view>
data:{
	colorList:[],//随机颜色
	isloading:false //是否正在请求
},
getColors(){
	this.setData({
		isloading:true
	})
	wx.showLoading({title:'数据加载中...'})//展示提示窗
	wx.request({
		url:"https://www.essss.cn/api/getcolor",
		method:'GET',
		success:({data:res})=>{
			this.setData({
				colorList:[...this.data.colorList,...res.data]
			})
		}complete:()=>{
			wx.hideLoading()//隐藏提示窗
			this.setData({
				isloading:false
			})
		}
	})
},
onLoad:function(options){
	this.getColors()
},
onReachBottom:function(){
//需要节流处理,防止上次没处理完再此请求
	if(this.data.isloading) return
	this.getColors()
}
.num-item{
	border:1rpx solid #efefef;
	border-radius:8rpx;
	line-height:200rpx;
	margin:15rpx;
	text-align:center;
	text-shadow:0rpx 0rpx 5rpx #fff;
	box-shadow:1rpx 1rpx 7rpx #aaa;
}

...展开运算符,用于对数组或者对象的操作,也可以将几个数组进行连接,参考

let arr=[1,2,3]
 // 展开一个数组
 console.log(...arr)

 console.log("-----------");
 // 复制一个数组,也称为拷贝数组
 let arr2=[...arr]
 arr2.push(4);
 // 并且不会对arr造成影响
 console.log("arr",arr);
 console.log("arr2",arr2);
 
 console.log("-----------");
 
 // 连接数组
 let arr3=[...arr,...arr2] 
 console.log(arr3);
 
//对象操作-------------------------------------------------
var obj1 = { foo: 'yuan', x: 42 };
var obj2 = { foo: 'li', y: 13 };

// 克隆对象一定要加上{}
var clonedObj = { ...obj1 };
console.log("克隆后的对象",clonedObj);
console.log("-----------");
// 同样的修改复制后的并不会影响原来的对象
clonedObj.foo="ss"
console.log("clonedObj",clonedObj);
console.log("obj1",clonedObj);
console.log("-----------");

// 合并后的对象:
var mergedObj = { ...obj1, ...obj2}
console.log("合并后的对象",mergedObj);

console.log("-----------");
// 当然也可以在合并时添加新的属性
var mergedObj = { ...obj1, ...obj2,address:"上海"}
console.log("合并后的对象",mergedObj)
   
原文链接:https://blog.csdn.net/qq_44259670/article/details/116397831

自定义编译模式

每次重新编译后,模拟器自动跳转到首页
普通编译 下拉➡添加编译模式➡启动页面 的值进行修改,启动参数也可以自动添加,如name=zs。
删除时,可以点击 添加编译模式 中的 自定义编译模式 边的修改按钮,删除。

生命周期

  1. 应用生命周期:小程序从启动➡运行➡销毁的过程
  2. 页面生命周期:页面的加载➡渲染➡销毁的过程

应用的生命周期函数

需要再app.js中进行声明。

App({
	//小程序初始化完成时,执行此函数,全局只触发一次,可以进行初始化
	onLaunch:function(options){ },
	//小程序启动,或从后台进入前台显示时触发。
	onShow:function(options){ },
	//小程序从前台进入后台时出发。
	onHide:function(){ }
})

页面的生命周期函数

需要再页面.js中进行声明。

Page({
	onLoad:function(options){ }, //监听页面加载,一个页面只能调用一次
	onReady:function(){ },//监听页面初次渲染完成,一个页面只能调用一次
	onShow:function(){ },//监听页面显示
	onHide:function(){ },//监听页面隐藏
	onUnload:function(){ },//监听页面卸载,一个页面只能调用一次
})

wxs脚本

wxs是微信小程序独有的脚本语言,结合wxml可以构建出页面的结构。
可以应用为过滤器。

  1. wxs有自己的数据类型,同js
  2. wxs不支持类似es6以上的语法,如let 箭头函数 展开运算符
  3. wxs遵循commonjs规范,如module对象,require()函数,module.exports

使用wxs脚本

wxs代码可以编写在wxml文件中的<wxs>标签内。
wxml文件中的每个<wxs>标签,必须提供module属性,用来指定当前wxs的模块名称,方便wxml中访问模块的成员。

<view>{{m1.toUpper(username)}}</view>
<wxs module="m1">
module.exports.toUpper = function(str){
	return str.toUpperCase()
}
</wxs>

外联wxs脚本
wxs代码还可以编写在 .wxs后缀的文件内,如:
//tools.wxs

function toLower(str){
	return str.toLowerCase()
}
module.exports = {
	toLower:toLower
}

应用外联wxs脚本时需要添加module和src属性(相对路径)

<wxs module="m2" src="../../utils/tools.wxs"></wxs>
<view>{{m2.toLower(username)}}</view>

注意:

  1. wxs的应用一般时作为过滤器,配合mustache语法使用,如上两个例子。
    不能进行作为组件的事件回调函数,例如不能以下写法:
<button bindtap="m2.toLower">按钮</button>
  1. wxs不能调用js中的函数和小程序中的API。

组件和样式

创建

  1. 项目根目录 右键 新建文件夹 创建 components 文件夹,下面创建 test 文件夹
  2. test 文件夹上 右键 新建Component
  3. 输入组件名称后回车,自动生成四个文件,js json wxml wxss

建议每个组件单独创建一个文件夹存放。

引用

  1. 局部引用:组件只能被当前页面引用
  2. 全局引用:组件可以在每个小程序页面中引用

局部应用:
页面.json 文件中引用

{
	"usingComponents":{
		"my-test1":"/component/test1/test1"
	}
}

页面给中使用组件

<my-test1></my-test1>

全局引用:
在app.json文件中,引入组件

{
	"pages":[],
	"usingComponents":{
		"my-test1":"/component/test1/test1"
	}
}

页面给中使用组件

<my-test1></my-test1>

组件文件

  1. 组件中的json文件中需要声明"component":true属性
  2. 组件的js文件中调用的是Component() 函数
  3. 组件的事件处理函数需要定义到methods节点中

组件样式隔离

组件间的样式不会影响到小程序和其他组件的样式,同样小程序和其他组件的样式也不影响到组件里的样式。
即组件内不可以使用app.wxss里面定义的样式类。
只用类选择器会被影响,id、标签、属性选择器不受影响,所以建议在组件中使用类选择器

修改组件样式隔离

通过styleIsolation修改,其可选值:

  1. isolated,默认值,启用样式隔离
  2. apply-shared 页面wxss样式将影响到组件,但组件wxss中的样式不会影响到页面。
  3. shared 页面wxss会影响到组件,组件wxss中的样式也会影响到页面和其他设置了shared和apply-shared的组件。

组件的js文件中增加配置:

Component({
	options:{
		styleIsolation:'isolated'
	}
})

或者在组件的json文件中增加配置:

{
	"styleIsolation":"isolated"
}

数据

需要定义到data节点中

Component({
	data:{
		count:0
	}
})

方法

组件中方法需要定义到methods节点中

Component({
	methods:{
		addCount(){ //事件处理函数
			//todo
		},
		_showCount(){// 自定义方法建议下划线_开头
			//todo
		}
	}
})

属性

properties 是组件对外的属性,用来接受外界传递到组件中的数据,示例如下:

Component({
	properties:{
		max:{	//完整定义属性的方式,需要指定属性默认值时,建议使用此方法
			type:Number,	//属性值的数据类型
			value:10		// 默认值
		},
		max:Number	//简化定义属性的方式,不需指定属性默认值时,可以使用简化方式
	},
	methods:{
		getMax(){
			return this.properties.max
		}
	}
})

使用:

<my-test max="10"></my-test>

data和properties区别

  1. 都是可读可写的
  2. data倾向于存储私有数据
  3. properties倾向于存储传递过来的数据
Component({
	properties:{
		max:{	//完整定义属性的方式,需要指定属性默认值时,建议使用此方法
			type:Number,	//属性值的数据类型
			value:9		// 默认值
		},
		max:Number	//简化定义属性的方式,不需指定属性默认值时,可以使用简化方式
	},
	methods:{
		printf(){
			console.log(this.data)
			console.log(this.properties)
			console.log(this.data === this.properties)
		}
	},
	data:{
		count:0
	}
})

在这里插入图片描述
调用printf,结果为true;证明data数据和properties在本质上是一样的,都是可读可写的。因此properties属性的值也可以用于页面渲染,或使用setData为properties中是属性重新赋值。

修改properties的值

Component({
	properties:{max:Number},
	methods:{
		addCount(){
			this.setData({max:this.properties.max + 1})
		}
	}
})
<view>properties{{max}}</view>

数据监听器

数据监听器用于监听和响应任何属性和数据字段的变化,执行特定的操作。类似与vue中的watch。

Component({
	data:{d1:0,d2:0},
	methods:{
		chg(){
			this.setData({
				d1:1
			})
		}
	},
	observers:{//数据监听器
		'd1,d2':function(newd1,newd2){//监听d1和d2的变化
			//todo
		}
	}
})

也可以监听对象的单个或多个属性,多个属性中如果其中一个变化则会触发监听器。

Component({
	data:{
		o:{a:o,b:1}
	},
	methods:{
		chg(){
			this.setData({
				o:{a:11,b:22}
			})
		}
	},
	observers:{//数据监听器
		'o.a,o.b':function(newd1,newd2){//监听o的a和b属性的变化
			//todo
		}
	}
})

案例:

Component({
	data:{
		rgb:{
			r:0,
			g:0,
			b:0
		},
		fullColor:'0,0,0'
	},
	properties:{
	
	},
	methods:{
		changeR(){
			this.setData({
				'rgb.r':this.data.rgb.r + 5 > 255 ? 255 :this.data.rgb.r + 5
			})
		},
		changeG(){
			this.setData({
				'rgb.g':this.data.rgb.g + 5 > 255 ? 255 :this.data.rgb.g + 5
			})
		},
		changeB(){
			this.setData({
				'rgb.b':this.data.rgb.b + 5 > 255 ? 255 :this.data.rgb.b + 5
			})
		},
	},
	observers:{
		'rgb.r, rgb.g, rgb.b':function(r,g,b){
			this.setData({
				fullColor: `${r},${g},${b}`
			})
		}
	}
})
<view style="background-color:rgb({{fullColor}});" class="colorBox">颜色值:{{fullColor}}</view>
<button size="mini" bindtap="changeR" type="default">R</button>
<button size="mini" bindtap="changeG" type="primary">G</button>
<button size="mini" bindtap="changeB" type="warn">B</button>
.colorBox{
	line-height:200rpx;
	font-size:24rpx;
	color:white;
	text-shadow:0rpx 0rpx 2rpx black;
	text-align:center;
}

如果要监听的属性过多,可以使用通配符**来监听所有属性的变化,如

observers:{
	'rgb.**':function(obj){
		this.setData({
			fullColor:`${obj.r},${obj.g},${obj.b}`
		})
	}
}

纯数据字段

指不用于渲染的data数据,如上例中的rgb,如果data中的字段既不展示到界面上,也不会传递给其他组件,仅仅在当前组件内部使用,这种特性的字段适合设置为纯数据字段。
有助于提升页面更新的性能。

使用规则:
在Component的options节点中,指定pureDataPattern为一个正则表达式,字段名称符合此正则表达式的字段将成为纯数据字段。如

Component({
	options:{
		//指定下划线开头的数据为纯数据字段
		pureDataPattern:/^_/
	},
	data:{
		a:true,//普通数据字段
		_b:true//纯数据字段,只应用于数据逻辑,不渲染到页面上
	}
})

监听纯数据字段:

Component({
	options:{
		//指定下划线开头的数据为纯数据字段
		pureDataPattern:/^_/
	},
	data:{
		_rgb:{
			r:0,
			g:0,
			b:0
		}
	},
	observers:{
	'_rgb.**':function(obj){
		this.setData({
			fullColor:`${obj.r},${obj.g},${obj.b}`
		})
	}
}
})

组件的生命周期

生命周期函数如下:

生命周期函数参数描述说明
created在组件实例刚刚被创建时调用
attached在组件实例进入页面节点树时执行
ready在组件在视图层布局完成后执行
moved在组件实例被移动到页面节点树另一个位置时执行
detached在组件实例被从页面节点树移除时执行
errorObject Error每当组件方法抛出错误时执行

顺序如表中的顺序。
重点使用以下几个:
created:
在组件被创建好的时候,该函数被触发;此时还不能使用setData,此阶段只能给组件的this添加一些自定义的属性字段。
attached:
该阶段,this.data已经被初始化完毕;绝大多数初始化工作可以在此阶段进行。
detached:
退出页面时,页面中的组件会触发detached;该阶段一般进行清理工作,如取消监听。

生命周期函数的使用

Component({
	//推荐使用
	lifetimes:{
		attached(){},
		detached(){}
	},
	//旧式的定义方式
	attached(){},
	detached(){}
})

新旧方式同时存在时,lifetimes中的生命周期函数会覆盖旧式的。

组件内部也可以监听 组件 所在 页面的生命周期,

生命周期函数参数描述
show组件所在页面被展示时执行
hide组件所在页面被隐藏时执行
resizeObject Size组件所在页面尺寸发生变化时执行

使用:

Component({
	pageLifetimes:{//监听所在页面的生命周期
		show(){},
		hide(){},
		resize(){}
	}
})

插槽

在wxml结构中,提供了一个** <slot> **节点(插槽),用于承载组件使用者提供的wxml结构。
可以理解为组件中预留的占位符,组件使用者提供具体的内容。

单个插槽
小程序中,默认每个自定义组件中只允许使用一个 slot 进行占位,这种个数上的限制,叫做单个插槽。

<!-- 组件的wxml -->
<view class="wrapper">
	<view>这里是组件的内部节点</view>
	<slot></slot>
</view>

<!-- 组件使用者的wxml -->
<component-tag-name>
	<view>这里是插入组件slot中的内容</view>
</component-tag-name>

多个插槽
启用多个插槽,在组件的js文件中进行配置:

Component({
	options:{
		multipleSlot:true//启用多个插槽
	}
})

多个slot标签,使用name来区分

<!-- 组件的wxml -->
<view class="wrapper">
	<slot name="before"></slot>
	<view>这里是组件的内部节点</view>
	<slot name="after"></slot>
</view>

<!-- 组件使用者的wxml -->
<component-tag-name>
	<view slot="before">这里是插入组件slot中的内容1</view>
	<view slot="after">这里是插入组件slot中的内容2</view>
</component-tag-name>

父子组件通信

  1. 属性绑定
    • 用于父组件向子组件的指定属性设置数据,仅能设置json兼容的数据(不能传递方法)
  2. 事件绑定
    • 用于子组件向父组件传递数据,可以传递任意数据
  3. 获取组件实例
    • 父组件可以通过 this.selectComponent()获取子组件实例的对象
    • 然后就可以直接访问子组件的任意数据和方法

属性绑定
父组件

<view> count值{{count}}</view>
<my-com count="{{count}}"></my-com>
data:{
	count:0
}

子组件

properties:{
	count:Number
}
<view> 子组件 count值{{count}}</view>

事件绑定

  1. 父组件的js中,定义一个函数,这个函数即将通过自定义事件的形式,传递给子组件。
  2. 父组件的wxml中,通过自定义事件的形式,将步骤1中定义的函数引用,传递给子组件。
  3. 子组件的js中,通过调用this.triggerEvent('自定义事件名称‘,{参数对象}),将数据发送到父组件。
  4. 父组件的js中,通过e.detail获取到子组件传递过来的数据

父组件

//父组件中定义syncCount 方法
syncCount(e){
	console.log("syncCount")
	console.log(e.detail.value)
}
<!-- 使用 bind:自定义事件名称(推荐:结构清晰) -->
<my-com count="{{count}}" bind:sonf="syncCount"></my-com>
<!-- 或者-->
<my-com count="{{count}}" bindsonf="syncCount"></my-com>

子组件

methods:{
	addcount(){
		this.triggerEvent('sonf',{value:this.properties.count})
	}
}

获取组件实例
在父组件中调用this.selectComponent("id或者css选择器"),获取子组件的实例对象,从而直接访问子组件的任意数据和方法。调用时需要传入一个选择器。

<my-com class="comA" id="ca"></my-com>
<button bindtap="getchd">get</button>
getchd(){
//不支持标签选择器
	const child = this.selectComponent('.comA')
	child.setData({//调用子组件的setData方法
		count:child.properties.count + 1
	})
	child.addCount()//调用子组件的方法
}

behaviors

用于实现组件间代码共享的特性,类似于vue中的mixins。
自定义组件A ←引用←代码共享(behavior)→引用→自定义组件B。
工作方式:
每个behavior 可以包含一组 属性、数据、生命周期函数 和方法。组件引用他时,他的属性、数据和方法会被合并到组件中。
每个组件可以引用多个behavior,behavior也可以引用其他的behavior。
创建behavior
调用Behavior(Object object)方法即可创建一个共享的behavior实例对象,供所有组件使用:
my-b.js

//调用 Behavior()方法,创建实例
//使用 module.exports 将 behavior 实例对象共享出去
module.exports = Behavior({
	//属性节点
	properties:{},
	//私有数据节点
	data:{username:'zs'},
	//事件处理函数 和 自定义方法节点
	methods:{},
	//其他节点
})

导入并使用behavior
在组件中,使用 require() 方法导入需要的behavior, 挂载后即可访问behavior中的数据或方法,如:

//1. 使用 require() 导入需要的自定义 behavior 模块
const myBehavior = require("../../behaviors/my-b")

Component({
	//2. 将导入的 behavior 实例对象,挂载到 behaviors 数组节点中,即可生效
	behaviors:[myBehavior],
	//组件的其他节点
})
<view>behavior:{{username}}</view>

behavior中可用的节点
propertie、data、methods、behaviors使用较多。

可用的节点类型是否必填描述
propertiesObject Map同组件的属性
dataObject同组件的数据
methodsObject同自定义组件的方法
behaviorString Array引入其他的behavior
createdFunction生命周期函数
attachedFunction生命周期函数
readyFunction生命周期函数
movedFunction生命周期函数
detachedFunction生命周期函数

behavior中同名字段的覆盖和组合规则
组价和它引用的 behavior 中 可以包含同名的 字段,处理规则如下:

  1. 数据(data)重名
    • 对象类型数据,会进行对象合并
    • 其余情况进行数据覆盖,组件 > 父behavior > 子behavior
  2. 属性(properties)和方法
  3. 生命周期函数

使用npm包

小程序支持npm包,但是有3个限制:

  1. 不支持依赖于 Node.js 内置库的包,如fs、path
  2. 不支持依赖于浏览器内置对象的包,如jquery
  3. 不支持依赖于c++插件的包,如一些加密包
    所以支持的包很少。

vant Weapp

前端开源 小程序UI组件库,使用MIT开源许可协议。
网址:https://youzan.github.io/vant-weapp/#/home

安装

  1. 通过npm安装,可以使@1.3.3版本
  • npm init -y,生成package.json
  • npm i @vant/weapp -S --production,安装vant Weapp,也可以指定版本号npm i @vant/weapp@1.3.3 -S --production
  1. 构建npm包
  • 工具→构建npm,勾选使用npm模块
  • 右上角 详情,勾选使用npm模块
  1. 修改app.json
  • 将 “style”:“v2” 删除,防止样式冲突

小程序中打开终端的方法:目录树空白处右键,在外部终端窗口打开。

使用

在 app.json 的 usingComponents 节点引入需要的组件。

"usingComponents":{
	"van-button":"@vant/weapp/button/index"
}
<van-button type="primary">按钮</van-button>

定制全局主题样式

使用css变量来实现定制主题。
声明自定义属性,属性名前需要加两个减号--,属性值可以使任意的css值。

/*在根伪类下定义变量,就可以在html文档的任何地方引用了,或者html{}中定义*/
:root{
	--my-define-color:brown;
	--my-define-width:10px;
}
p{
	background-color:var(--my-define-color);
	width:var(--my-define-width,5px);
	/*,5px表示不确定--my-define-width是否存在,如果不存在,则按照5px来设置width*/
}

在小程序中,app.wxss文件里,写入css变量,即可对全局生效:

page{
	--button-danger-background-color:#efef00;
	--button-danger-border-color:#efef00;
}

小程序的根节点为page,所以定义到page下。
可在官网的定制主题里查找对应的css变量名称。

API Promise化

基于回调函数的异步API,容易造成回调地狱。
API Promise化,就是通过额外的配置,将官方的API改造成promise的异步api。

实现

依赖第三方npm包,miniprogram-api-promise。
安装:npm install --save miniprogram-api-promise@1.0.4
小程序安装新的npm包后,需要进行构建,防止出错,可以将miniprogram_npm文件夹删除。

在小程序入口文件app.js中,调用一次 promiseifyAll() 方法,即可实现 Promise 化。

import { promisifyAll } from 'miniprogram-api-promise'

const wxp = wx.p = {}
promisifyAll(wx, wxp)

使用Promise化的API

页面js

async getInfo(){
	const { data:res } = await wx.p.request({
		method:'GET',
		url:'https://www.escook.cn/api/get',
		data:{name:'zs',age:30}
	})
	console.log(res)
}

全局数据共享

全局数据共享(又叫状态管理),是为了解决组件之间数据共享的问题。
常用的数据共享方案有:vuex,redux,MobX等。

小程序中的全局共享

使用mobx-miniprogram配合mobx-miniprogram-bindings实现全局数据共享。

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

安装MobX

npm install --save mobx-miniprogram@4.13.2 mobx-miniprogram-bindings@1.21
安装完毕后, 需要删除 miniprogram_npm 后,重新工具→构建 npm

创建 MobX

根目录下创建store文件夹,下创建store.js,用来存储数据

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

export const store = observable({
	//存放共享数据
	//数据字段
	numA:1,
	numB:2,
	//计算属性,方法名 前 增加 get
	get sum(){
		return this.numA + this.numB
	}
	//actions 方法,用来修改 store 中的数据,只能通过actions修改,不可直接改
	updateNum1:action(function(step){
		this.numA += step
	}),
	updateNum2:action(function(step){
		this.numB += step
	})
})

页面使用

页面js文件

import { createStoreBindings } from 'mobx-miniprogram-bindings'
//导入实例对象,store文件夹中的store.js
import { store } from '../../store/store'

Page({
	onload:function(){
		//将当前页面与数据绑定
		this.storeBindings = createStoreBindings(this, {
			store,//绑定的数据源
			fields:['numA','numB','sum'],//数据、属性字段
			actions:['updateNum1']//导入的方法
		})
	},
	onUnload:function(){
		this.storeBindings.destroyStoreBindings()
	},
	handle1(e){//按钮处理函数
		this.updateNum1(e.target.dataset.step)
	}
})

页面wxml

<view>{{numA}} + {{numB}} = {{sum}}</view>
<van-button type="primary" bindtap="handle" data-step="{{1}}">
	numA + 1
</van-button>
<van-button type="danger" bindtap="handle" data-step="{{-1}}">
	numA - 1
</van-button>

组件中使用

将store中的成员绑定到组件中
组件js文件

import { storeBindingsBehavior } from 'mobx-miniprogram-bindings'
//导入实例对象,store文件夹中的store.js
import { store } from '../../store/store'

Component({
	behaviors:[ storeBindingsBehavior ],//通过 storeBindingsBehavior  实现自动绑定
	storeBindings:{
		store,//指定要绑定的 store
		fields:{//指定要绑定的字段数据
			numA:()=>store.numA,//绑定字段的方式1
			numB:(store)=>store.numB,//绑定字段的方式2
			sum:'sum'//绑定字段的方式3
		},
		actions:{//绑定方法
			updateNum2:'updateNum2'
		}
	},
	methods:{
		handle(e){
			this.updateNum2(e.target.dataset.step)
		}
	}
})
<view>{{numA}} + {{numB}} = {{sum}}</view>
<van-button type="primary" bindtap="handle" data-step="{{1}}">
	numB + 1
</van-button>
<van-button type="danger" bindtap="handle" data-step="{{-1}}">
	numB - 1
</van-button>

分包

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

  1. 首次启动时缩短下载时间
  2. 协同开发

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

  • 主包:一般只包含项目的启动页面或tabBar页面、以及所有分包需要的一些公共资源
  • 分包:只包含和当前分包相关的页面和私有资源

分包的加载规则:

  1. 小程序启动时,默认会下载主包并启动主包内页面:
    tabBar 页面需要放在主包中
  2. 当用户进入分包内某个页面时,客户端会把对应分包下载下来,下载完成后再进行展示
    非tabBar页面可以按照功能的不同,划分为不同的分包之后,进行按需下载。

体积限制:

  1. 整个小程序的所有分包大小不超过16M
  2. 单个分包、主包大小不能超过2M

分包的使用需要在app.json 的 subpackages 节点中声明分包的结构:
在这里插入图片描述

{
"pages":[//主包的所有页面
	"pages/index",
	"pages/logs"
]
"subpackages":[//通过subpackages 节点,声明分包结构
	{
		"root":"packageA",//第一个分包根目录
		"pages":[//当前分包下,所有的页面的相对存放路径
			"pages/cat",
			"pages/dog"
		]
	},
	{
		"root":"packageB",//第二个分包的根目录
		"name":"pack",//分包的别名
		"pages":[//当前分包下,所有的页面的相对存放路径
			"pages/apple",
			"pages/banana"
		]
	}
]
}

创建分包:
可以在app.json中,直接完善subpackages节点,保存后,开发者工具会自动生成对应的文件。

查看分包大小:
开发工具右上角,详情,基本信息下方展开 本地代码 查看
在这里插入图片描述
打包规则:

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

引用原则:

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

独立分包

独立分包本质也是分包,但是可以独立于主包和其他分包单独运行。
普通分包必须依赖主包运行。
独立分包可以在不下载主包的情况下,独立运行。独立分包可以不下载主包,提高启动速度。一个小程序中可以有多个独立分包。
在这里插入图片描述
通过 independent 节点 声明当前分包为独立分包。

{
"pages":[//主包的所有页面
	"pages/index",
	"pages/logs"
]
"subpackages":[//通过subpackages 节点,声明分包结构
	{
		"root":"moduleA",//普通分包根目录
		"pages":[//当前分包下,所有的页面的相对存放路径
			"pages/cat",
			"pages/dog"
		]
	},
	{
		"root":"moduleB",//第二个分包的根目录
		"pages":[//当前分包下,所有的页面的相对存放路径
			"pages/apple",
			"pages/banana"
		],
		"independent":true//声明当前分包为独立分包
	}
]
}

独立分包的引用原则:
独立分包和普通分包、主包之间,相互隔绝,不能互相引用彼此的资源。

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

分包预下载
进入小程序的某个页面时,由框架自动预下载可能需要的分包,从而提升进入后续分包页面的速度。
配置分包预下载配置(preloadRule):

//app.json
{
	"preloadRule":{//分包预下载的规则
		"pages/contact/contact":{//触发分包预下载的页面路径
			// network 表示在指定网络模式下进行预下载
			//可选值:all(不限网络)和wifi(进wifi模式下进行预下载)
			// 默认值: wifi
			"network":"all",
			// packages 表示进入页面后,预下载哪些分包
			// 可以通过root 或者 name 指定预下载哪些分包
			"packages":["pkgA"]
		}
	}
}

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

案例

自定义tabBar

  1. app.json tabBar节点增加 custom:true;表示使用自定义tabBar。
  2. 新建名为custom-tab-bar的文件夹,必须为此名称;下面增加名为index的组件,必须叫index:右键,新建component,index。
  3. 基于vant组件,完善index.wxml。app.json引入组件。
  4. 使用自定义的tabbar图标和文本,从data中的list使用数据
  5. 循环渲染tabbar的item项
  6. 通过css变量修改tabbar图标的margin-bottom值
  7. 使用list中info的值渲染徽标数字
  8. 将全局数据中的num监听,同步到data的info中
  9. 使用全局数据中的active控制页面切换记录
    10.修改tabbar文字的颜色

app.json

{
    "pages": [
        "pages/list/list",
        "pages/message/message",
        "pages/info/info"
    ],
    "window": {
        "backgroundTextStyle": "light",
        "navigationBarBackgroundColor": "#D8322E",
        "navigationBarTitleText": "小微祝福",
        "navigationBarTextStyle": "white"
    },
    "tabBar": {
        "custom": true,
        "list": [{
            "pagePath": "pages/list/list",
            "text": "列表",
            "iconPath": "image/ln.png",
            "selectedIconPath": "image/la.png"
        },{
            "pagePath": "pages/message/message",
            "text": "消息",
            "iconPath": "image/mn.png",
            "selectedIconPath": "image/ma.png"
        },{
            "pagePath": "pages/info/info",
            "text": "我的",
            "iconPath": "image/in.png",
            "selectedIconPath": "image/ia.png"
        }]
    },
    "style": "v2",
    "sitemapLocation": "sitemap.json",
    "usingComponents":{
        "van-button":"@vant/weapp/button/index",
        "van-tabbar":"@vant/weapp/tabbar/index",
        "van-tabbar-item":"@vant/weapp/tabbar-item/index"
    }
}

store.js

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

export const store = observable({
    num:7,
    active:0,
    setActive:action(function(newValue){
        this.active = newValue
    })
})

index.html

index.wxml
<van-tabbar active="{{ active }}" bind:change="onChange" active-color="#990101">
  <van-tabbar-item wx:for="{{list}}" wx:key="index" info="{{item.info ? item.info : ''}}" >
    <image slot="icon" src="{{item.iconPath}}" mode="aspectFit" style="width: 30px;height:18px;" />
    <image slot="icon-active" src="{{item.selectedIconPath}}" mode="aspectFit" style="width: 30px;height:18px;" />
    {{item.text}}
  </van-tabbar-item>
</van-tabbar>

index.js

// custom-tab-bar/index.js
import {storeBindingsBehavior} from 'mobx-miniprogram-bindings'
import {store} from '../store/store'
Component({
    options:{//进行样式覆盖需要设置
        styleIsolation:'shared'
    },
    observers:{
        'num':function(val){
            this.setData({
                'list[1].info':val
            })
        }
    },
    behaviors:[storeBindingsBehavior],
    storeBindings:{
        store,
        fields:{
            num:'num',
            active:'active'
        },
        actions:{
            setActive:'setActive'
        }
    },
    /**
     * 组件的初始数据
     */
    data: {
        "list": [{
            "pagePath": "/pages/list/list",
            "text": "列表",
            "iconPath": "/image/ln.png",
            "selectedIconPath": "/image/la.png"
        },{
            "pagePath": "/pages/message/message",
            "text": "消息",
            "iconPath": "/image/mn.png",
            "selectedIconPath": "/image/ma.png",
            info:2
        },{
            "pagePath": "/pages/info/info",
            "text": "我的",
            "iconPath": "/image/in.png",
            "selectedIconPath": "/image/ia.png"
        }]
    },

    /**
     * 组件的方法列表
     */
    methods: {
        onChange(event){
            this.setActive(event.detail)
            console.log(this.data.list[event.detail].pagePath)
            wx.switchTab({
              url: this.data.list[event.detail].pagePath,
            })
        }
    }
})

index.css

/* custom-tab-bar/index.wxss */
.van-tabbar-item{
    --tabbar-item-margin-bottom:0;
}

常见错误

渲染层错误ReferenceError: __g is not defined

删除app.json中的 “lazyCodeLoading”: “requiredComponents”

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值