本篇文章是笔者在学习微信小程序的过程中写下的笔记,之所以写这篇是因为csdn上几乎没有一篇博客能够系统的记录小程序的学习,我希望这篇博客能给想要看文档学习小程序的同学提供一些帮助。
另外,关于小程序的学习我强烈建议有vue操作的人来学习,因为小程序的思路和原理与vue及其稳和,所以如果大家在学习过程中需要复习vue,可以看我的这篇博客:
万字复盘Vue2相关知识(适合学过但忘了然而需要上手的朋友)
如果学习中有问题也可也私信我交流或者评论区一起交流。私信一般会回!
话不多说,码字不易,希望大家多点赞多关注收藏!!咱们开始学习!
小程序与普通网页开发:
运行环境:网页运行在浏览器中,小程序用于微信中;
API:小程序无法调用浏览器中的DOM和BOM的API,但是可以调用微信环境提供的API(地理定位、扫码、支付);
开发模式:网页的开发(浏览器+代码编辑器),小程序,申请开发账号,安装开发者工具,创建和配置小程序项目。
注册开发账号:https://mp.weixin.qq.com/
点击立即注册,选择小程序,接着走流程即可。
在注册好之后,可以获取AppID。
作用:创建项目、编辑调试代码、调试功能、小程序预览与发布。
下载安装包后安装即可。
安装完成后,微信扫码打开登录
这属于一项配置,直接操作即可。
点击加号按钮:
配置好一些信息,设置存放目录后,把之前的AppID复制过去,不使用云服务,确保语言是js。
完成配置后,点开,页面如此:
左侧是页面模拟器,右边有一个编译的按钮,点击后,就可解析代码到左侧的模拟器中。
点击帮助,开发者文档即可打开:
pages:存放项目中所有小程序页面;
utils:所有工具性质的模块(如格式化时间);
app.js:小程序项目入口文件;
app.json: 小程序项目的全局配置文件;
app.wxss:小程序项目的全局样式文件(全局);
project.config.json:项目的配置文件;
sitemap.json:用来配置小程序及其页面是否允许被微信索引。
.js:脚本文件,存放数据,事件处理函数等;
.json:配置文件,配置窗口外观,表现等;(json文件一般都是配置文件)
.wxml:页面模板结构摁键;
.wxss:当前页面的样式表文件。
当前小程序的全职配置,包括:页面路径、窗口外观、界面表现、底部tab等。
下面是初始化app.json文件的代码:
{
"pages":[
"pages/index/index",
"pages/logs/logs"
],
"window":{
"backgroundTextStyle":"light",
"navigationBarBackgroundColor": "#fff",
"navigationBarTitleText": "Weixin",
"navigationBarTextStyle":"black"
},
"style": "v2",
"sitemapLocation": "sitemap.json"
}
pages:用来记录当前小程序所有页面路径;
window:全局定义小程序所有页面的背景色、文字颜色等;
style:全局定义小程序组件所使用的样式版本;
sitemapLocation:用来指明sitmap.json的位置。
这个文件一般用于做一些自定义配置,本节看一下基本配置。
appid:如果拿到一个别人的项目,可以把appid改成自己的,就可以在自己的电脑上运行:
projectname:项目名称,不等于小程序名称。
配置小程序页面是否允许微信索引:
{
"desc": "关于本文件的更多信息,请参考文档 https://developers.weixin.qq.com/miniprogram/dev/framework/sitemap.html",
"rules": [{
"action": "allow",
"page": "*"
}]
}
上面这段代码,page后面是星号,表示所有页面,action后面是allow,表示所有页面都允许被索引。(不允许可以改成disallow)
对本页面的窗口外观进行配置,页面中的配置项会覆盖app.jsono的window中相同的配置项。
app.json是全局配置,如果页面配置与全局配置发生冲突,则依照页面配置来。
注意,文章中只要更改了代码,都要ctrls保存一下,右边才会有显示。
只需要在pages中新增页面存放路径,小程序开发者工具会自动帮我们创建页面文件:
WXML是小程序框架设计的一套标签语言,用老构建小程序页面的结构,类似网页开发中的HTML。
WXML和HTML区别
标签名称不同:
HTML(div、span、img、a)
WXML(view、text、image、navigator)
属性节点不同:
超链接
提供了类似Vue中的模板语法:
数据绑定、列表渲染、条件渲染
新增了rpx尺寸单位:
CSS需要手动单位换算,如rem;
WXSS在底层支持新的尺寸单位rpx,在不同大小屏幕上自动换算
提供了全局样式和局部样式:
项目根据app.wxss设置全局页面,局部页面.wxss仅对自己的页面生效
WXSS仅支持部分CSS选择器。
类选择器、id选择器、元素选择器、并集选择器、后代选择器、伪类选择器
app.js:入口文件,可调用App()函数来启动整个小程序;
页面.js:页面入口文件,通过调用Page()函数来创建并运行页面;
普通.js: 用来封装公共函数或者属性供页面使用。
宿主环境:程序运行所必须的依赖环境。
安卓和IOS系统是两个不同的宿主环境,脱离了宿主环境的软件是没有任何意义的。
这里以安卓为例。同样,IOS系统也有一套IOS系统的宿主环境(不放图了以此类推)。
1.通信模型
通信主体:渲染层和逻辑层
渲染层与逻辑层通过微信客户端进行通信。
2.运行机制
启动过程:
下载包->解析app.json->执行app.js,通过App()->渲染小程序首页->启动完成
页面渲染:
加载.json->加载.wxml模板和.wxss样式->执行.js文件,调用Page()->渲染完成
组件的存在,是为了代码的复用。系统封装好的导航,按钮,我们可以拿过来直接用,这就是组件。
官方把小程序组件分为九大类:==视图容器、基本内容、表单组件、导航组件、==媒体组件、map地图组件、canvas画布组件、开放能力、无障碍访问。
本节内容将带领读者了解小程序的常用组件。
本节讲一些微信小程序的常用组件。
注意哦,wxss几乎与css一样,后文基于样式的,不详细讲,按照css来写即可。
一开始打开后:
但是如果我们要在其中一个页面中写样式,如何在模拟器中查看呢?
在app.json中改变地址顺序即可:
先介绍view。view可以理解为div,也可也当div去用。在list中的wxml中的代码:
<view class="container1">
<view>Aview>
<view>Bview>
<view>Cview>
view>
可以在wxss中写样式,样式的写法和css一样。
实现纵向滚动效果:
做法,在刚刚的基础上,把外面的标签改为scroll-view;如果纵向滚动,在外侧加一个强制属性:scr0ll-y,并且给scroll-view指定一个高度;如果是横向滚动,则强制属性为scroll-x,并且给scroll-view指定一个宽度。
可以看下代码:
.wxml:
<scroll-view class="container1" scroll-y>
<view>Aview>
<view>Bview>
<view>Cview>
scroll-view>
轮播图组件用swiper和swiper-item来做。
外层用swiper包裹,内层用swiper-item来做。swiper-item内部可以自己写。看一下代码:
<swiper class="container2">
<swiper-item>
<view class="item">Aview>
swiper-item>
<swiper-item>
<view class="item">Bview>
swiper-item>
<swiper-item>
<view class="item">Cview>
swiper-item>
swiper>
最后效果出来,就是个轮播
样式也可自己写,写完样式就很好看,下面这个是轮播过程截的图:
指示点:indicator-dots
指示点颜色:indicator-color
指示点选中颜色:indicator-active-color
是否自动切换:autoplay
自动切换时间间隔:interval
是否采用衔接滑动:circular(到头了是否衔接到第一张)
本节讲解text与rich-text
text:文本组件,类似于html中的span标签,是一个行内元素;
rich-text:富文本组件,支持把html字符串渲染为wxml结构。
先看text,只有text属性又selectable属性,这个属性出现之后可以长按选中:
<view>
<text selectable>2092844344text>
view>
通过rich-text组件的nodes属性节点,可以把html字符串渲染为对应的ui结构。
按钮组件,功能比html中的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 plain>默认按钮button>
<button type="primary" size="mini" plain>按钮button>
<button type="warn" size="mini" plain>警告按钮button>
图片组件,image组件默认宽度约300px,高约240px。
image中有一个mode属性,用来指定图片的裁剪和缩放模式,常用的mode属性值如下:
scaleToFill:默认值,缩放模式,不包吃纵横比缩放图片,使图片的宽高完全拉伸至填满image元素;
aspectFit:缩放模式,保持纵横比缩放图片,使图片可以完整显示;
aspectFill:缩放模式,只保证图片的短边可以完全显示出来;
widthFix:缩放模式,宽度不变,高度自动变化(保持原图宽高比不变);
heightFix:缩放模式,高度不变,宽度自动变化(保持原图宽高比不变)。
大家可以拿来试一下。
页面导航组件,类似于html中的a链接。有机会单独出一篇博客。
在app.json文件中有一个样式版本:
style后面是v2是目前最新版本的样式。如果删掉,样式会发生很大变化,以按钮为例吧:
样式也是要基于需求的。
基本原则:在当前页面对应的.js文件中有个data,在data中定义数据,在WXML中使用数据,与Vue非常类似。
我们现在往里面写数据:
Mustache语法:{{}},两个大括号,数据在data中定义好了,在页面中使用直接:
<view>{{要绑定的数据名称}}view>
绑定内容
刚刚上面讲的就是动态绑定内容
绑定属性
比如我的wxml中有一个image,但是src不是固定的,那么我们可以动态绑定地址数据:
这里需要注意一下,写法与vue稍有差别。vue中img中的src可以采取单向绑定v-bind,但是这里直接用模板语法就好了。
绑定计算
在模板语法中是可以对数据进行操作的
三元运算:
在Appdata中可以查看到全部数据:
事件是什么?==是渲染层到逻辑层的通讯方式。==渲染层(页面)->逻辑层(js代码),中间的方式是事件。
事件有哪些?点击事件,鼠标移动事件等等。
小程序中常用的事件:
类型 | 绑定方式 | 事件描述 |
---|---|---|
tap | bindtap 或 bind:tap | 手指触摸后马上离开,类似于Html中的click事件 |
input | bindinput 或 bind:input | 文本框的输入事件 |
change | bindchange 或 bind:change | 状态改变时触发 |
事件回调触发,会收到一个参数event(对象),对象有这些属性:
属性 | 类型 | 说明 |
---|---|---|
type | String | event.type获取,反应事件类型 |
timestamp | Integer | 页面打开到触发事件所经过的毫秒数 |
target | Object | 触发事件的组件(遇到冒泡就是源头组件)的一些属性集合 |
currentTarget | Object | 当前所绑定的组件的一些属性值集合 |
detail | Object | 额外的信息 |
touches | Array | 触摸事件,当前停留在屏幕中的触摸点信息的数组 |
changedTouches | Array | 触摸事件,当前变化的触摸点信息的数组 |
在小程序中,通过tap事件来响应用户的触摸行为。现以bindtap为例讲解。
现给按钮绑定触摸事件:
<button type="primary" bindtap="clickit">按钮button>
接着在js中编写回调
// 回调
clickit(e) {
console.log(e)
}
通过调用this.setData(dataObject)方法,可以给页面data中的数据重新赋值。
需求:在data中定义一个count,页面上有个按钮,点击后data自增。
给按钮绑定事件:
<button type="primary" bindtap="addcount">点击后count值自增button>
addcount() {
this.setData({
count: this.data.count+1
})
},
在vue的事件中,可以直接在函数括号内传递参数,但是小程序中不行,小程序会默认把括号内的字符串当作事件名称来处理。
传参方式:为组件提供 data-*自定义属性传参,其中星号代表的是参数的名字。
传参方法:event.target.dataset.参数名可获取到具体的参数的值。
点击按钮后,count+2:
<button type="primary" bindtap="canshu" data-info="{{2}}">count+传参button>
canshu(e) {
this.setData({
count: this.data.count + e.target.dataset.info
})
},
在小程序中,通过input事件来响应文本框输入事件。
先定义文本框,注意,输入框默认是看不见的,但是鼠标过去光标会一闪一闪的。是存在的。
在json文件中配置:
// input的内容
inputHandler(e) {
console.log(e.detail.value)
},
美化样式
在小程序中,使用wx:if="{{}}"来判断是否需要渲染代码块
定义一个判断调价type:
使用wx:if进行条件渲染,根据type的值来展示对应信息:
最后结果:
同样还可以由elif,else:
上面这个就跟if的逻辑是一样的。但是要注意的是,else中什么都不用写。
如果有多个wx:if可以使用包裹标签block进行包裹,一次性的控制内容显示或隐藏:
block类似于vue中的template,不参与页面结构,不会把block渲染出来,避免渲染出一些不必要的结点。
使用hidden也可也控制元素的显示和隐藏。
wx:if以动态创建和移除元素的方式,控制元素的显示和隐藏;(移除后结构不存在)
hidden以切换样式的方式,类似于display,控制元素的显示和隐藏。(结构存在但是隐藏)
使用情况:
频繁切换的时候,建议使用hidden;不频繁可以使用wx:if,目的在于提高性能。
可以根据指定的数组,循环渲染重复的组件结构。
在data中定义一个数组arr:
接着在页面中渲染,这个我觉得比vue要高级一点,小程序中数组的index和item都是内置的,index是索引,item是索引对应的项。
直接就可以渲染在页面中:
类似于vue中的:key,小程序在实现列表渲染,也建议为渲染出来的列表项指定唯一的key,从而提高渲染的效率。
解释一下,这里的key是当前项的唯一标识(id),但是最好不要用index作为key使用。
有个建议,每用一个数组都要带上这个wx:key,是为了提高渲染性能,否则在终端中会出现黄色警告
上面的内容讲了很多,都在围绕着wxml来讲解。因为内容很多,所以分了很多个大块。后面wxss的内容较少,所以一个块讲解就够了,也就是下面的这一个。
wxss是一套样式语言,类似于css。
wxss具有大部分css特性,并且还对css进行了扩展——rpx尺寸单位于@import样式导入。
rpx是微信小程序独有的,用来解决适配的尺寸单位。
实现原理:把所有屏幕宽度上等分为750份。(当前屏幕的总宽度为750rpx)
在较小的设备上,1rpx所代表的宽度较小;
在较大的设备上,1rpx所代表的宽度较大。
当小程序在不同设备上运行的时候,会自动把rpx的样式单位换算成对应的像素单位来渲染,从而实现屏幕适配。
那么,rpx与px怎么换算?
在iphone6上(标准,标准设计稿),屏幕宽度为375px,共有750个物理像素,等分为750rpx,则1px = 2rpx,也就是说,1rpx = 0.5px;
其他手机型号换算多少会有些不一样,但是这个不影响,实际开发都是用rpx,页面会在不同设备上进行自动缩放。
使用wxss提供的@import语法,可以导入外联的样式表。
@import后面需要导入外联样式表的相对路径,用;表示语句结束。
举个例子,新建一个common作为公共样式表:
在内部定义公共样式:
在另一个模块导入这个样式表:
于是在当前模块可以看到效果:
全局样式可以理解为所有页面都遵循的样式;而局部央视只为所在页面服务。
全局样式在app.wxss中编写,而局部样式在当前页面的文件夹内部的wxss文件中编写。
注意,当局部样式和全局昂是冲突,根据就近原则,局部样式会覆盖全局样式
当局部样式权重大于或等于全局样式的权重,才会覆盖全局样式。
小程序根目录下的app.json文件是小程序的全局配置文件,常用配置:
pages:
记录当前小程序所有页面的存放路径;
window:
全局设置小程序窗口的外观;
tabBar:
设置小程序底部的tabBar效果;
style:
是否启用新版的组件样式。
一个个说吧,pages之前讲过,但是唯一要注意的是pages中的页面顺序,第一个页面是展示页面,比如下面这个,展示的就是wcs页面:
style上文在讲按钮的时候也说过,style是组件的样式版本,如果改动,样式会有很大的改变。
比较重要的就是,window和tabBar。
本节的重点也在这两个上面。
window的几个部分:
头部导航栏,有微信两字的栏目;
背景区域,默认不展现,下拉展现:
主体部分,除却导航栏下面的展示部分。
window中有很多常用配置项:
属性名 | 说明 |
---|---|
navigationBarTitleText | 导航栏标题文字内容 |
navigationBarBackgroundColor | 导航栏背景色 |
navigationBarTextStyle | 导航栏标题颜色,仅支持black/white |
backgroundColor | 窗口背景色 |
backgroundTextStyle | 下拉loading样式,仅支持dark/light |
enablePullDownRefresh | 布尔值,是否全局开启下拉刷新 |
onReachBottomDistance | 数字类型,页面上拉触底事件触发时距页面底部距离(距离底部多少px刷新页面),单位px |
以上颜色几乎都是十六进制代码。
可以拿着下面这段代码去试试:
"window": {
"backgroundTextStyle": "light",
"navigationBarBackgroundColor": "#fc5531",
"navigationBarTitleText": "巧克力小猫猿",
"navigationBarTextStyle": "white",
"enablePullDownRefresh": true,
"backgroundColor": "#efefef",
"onReachBottomDistance": 20
},
用于实现多页面的快速切换。
小程序中分为两类:底部tabBar,顶部tabBar,如下图所示:
注意:
tabbar内部只能配置最少两个,最多五个tab页签;
当渲染顶部tabBar,不显示icon,只显示文本。
属性名 | 说明 |
---|---|
backgroundColor | tabBar的背景色 |
selectediconPath | 选中时的图片路径 |
borderStyle | tabBar上边框的颜色 |
iconPath | 未选中时的图片路径 |
selectedColor | tab上的文字选中时的颜色 |
color | tab上文字的默认(未选中)颜色 |
list(必填) | tab页签的列表(最少2个最多5个) |
list中每个tab项的配置选项:
属性名 | 说明 |
---|---|
pagePath(必填) | 页面路径,页面必须在pages中预先定义 |
text(必填) | tab上显示文字 |
iconPath | 未选中时候的图标路径 |
selectedIconPath | 选中时图标路径 |
这里有个例子,可以拿去试一下:
"tabBar": {
"selectedColor": "#00b26a",
"list":[
{
"pagePath": "pages/wcs/wcs",
"text": "样式",
"iconPath": "/images/1.png",
"selectedIconPath": "/images/1.png"
},
{
"pagePath": "pages/model/model",
"text": "模型",
"iconPath": "/images/2.png",
"selectedIconPath": "/images/2.png"
},
{
"pagePath": "pages/list/list",
"text": "列表",
"iconPath": "/images/3.png",
"selectedIconPath": "/images/3.png"
},
{
"pagePath": "pages/index/index",
"text": "首页",
"iconPath": "/images/4.png",
"selectedIconPath": "/images/4.png"
}
]
},
需要注意的是,tabBar中的页面一定要在Page属性中的前面。
页面配置在页面的json文件中,配置内容几乎与全局配置一样。
需要注意的是,当页面配置与全局配置产生冲突时,会覆盖相同的全局配置。
还有一个注意点:一般情况下,页面不需要都配置下拉刷新,是根据需要来的。所以不建议在全局配置中配置这一项。
出于安全性考虑,小程序官方对数据接口的请求做出了如下两个限制:
只能请求Https类型的接口;
必须将接口的域名添加到信任列表中;
需求:在自己的小程序中,希望请求https://www.escook.cn域名下的接口
配置步骤:
登录微信小程序管理后台–>开发–>开发设置–>服务器域名–>修改request合法域名。
比如说,我们的项目想请求这个接口:https://www.escook.cn,就要把这个配置到request合法域名(填写request对应的表单即可,其他不用管)。配置完后,结果:
再打开开发者工具后,就自动有相关配置,我们的小程序就可以请求这个域名下的所有接口了:
注意:域名只支持https协议,且不能使用IP地址或localhost,域名必须镜柜ICP备案,且服务器域名一个月内最多可申请5次修改。
发起get请求:比如我在index中设置一个按钮,并绑定事件getInfo,点击发起get请求:
接着我们去配置getInfo,注意,这个函数与data平级:
getInfo() {
wx.request({
url: 'https://www.escook.cn/api/get',
method: 'GET',
data: {
name: 'zs',
age: 20
},
success: (res) => {
console.log(res.data)
}
})
},
post请求:很类似,都是调用wx.request():
postInfo() {
wx.request({
url: 'https://www.escook.cn/api/post',
method: 'POST',
data: {
name: 'ls',
age: 23
},
success: (res) => {
console.log(res)
}
})
},
在很多情况下,我们需要在页面刚加载的时候,自动请求一些初始化的数据:在onload事件中调用获取数据的函数。
就类似于vue中的mounted生命周期函数。onload事件是微信小程序的生命周期函数,用于监听页面的加载。
如果后端程序员仅仅提供了http协议的接口,暂时没有提供https协议的接口,该怎么办?
为了不耽误开发进度,可以在微信开发者工具中,==临时开启“开发环境不校验请求域名,TLS版本及HTTPS证书”选项,跳过request合法域名的校验。
在详情里面:
注意哦,这个没办法上线,只供开发与调试阶段使用。
跨域问题只存在于基于浏览器的web开发中,由于小程序的宿主环境不是浏览器,而是微信客户端,所以==小程序不存在跨域问题。
另外,Ajax的核心是基于浏览器中的XMLHttpRequest对象,而小程序宿主环境是微信客户端,所以小程序不能叫做发“发起Ajax请求”,而是叫做“发起网络数据请求”。
页面导航指的是页面之间的相互跳转。
浏览器中,实现页面导航的方式:a连接和location.href。
小程序中也有两种方式实现页面导航:声明式导航和编程式导航。
声明式导航:
在页面上声明一个navigator的导航组件,通过点击navigator组件实现页面跳转。
可以使用navigator组件跳转到指定的tabBar页面,需要指定url属性和open-type属性。
url:表示要跳转的页面的地址,必须以/开头;
open-type:表示跳转方式,必须为switchTab。
非tabBar:没有配置到tabBar的页面
跟上面的一样,我们在首页弄个链接:
点击后就可导航到info页面。
open-type值必须是navigateBack;
编程式导航是写代码进行跳转。
调用wx.switchTab(Object Object)方法,可以跳转到tabBar页面。其中Object参数对象的属性列表如下:
属性 | 是否必选 | 说明 |
---|---|---|
url | 是 | 需要跳转的tabBar页面的路径,路径后不能带参数 |
sucess | 否 | 接口调用成功后回调 |
fail | 否 | 接口调用失败后回调 |
complete | 否 | 接口调用结束的回调函数 |
编程式导航示例,先在首页写个按钮:
接着写跳转的相关代码:
上面这个办法只适合tabBar页面。
调用vx.navigateTo(Object, Object)方法,可以跳转非tabBar的页面,其中,Object参数对象属性列表:
属性 | 是否必选 | 说明 |
---|---|---|
url | 是 | 需要跳转非tabBar页面的路径,路径后不能带参数 |
sucess | 否 | 接口调用成功后回调 |
fail | 否 | 接口调用失败后回调 |
complete | 否 | 接口调用结束的回调函数 |
调用navigateBack(Object, Object)方法,参数对象可选属性列表:
属性 | 是否必选 | 说明 |
---|---|---|
delta | 否 | 默认值为1,返回的页面数,如果delta大于现有页面数则返回到首页 |
sucess | 否 | 接口调用成功后回调 |
fail | 否 | 接口调用失败后回调 |
complete | 否 | 接口调用结束的回调函数 |
navigator组件的url属性用来指定将要跳转的页面路径,同时,页面路径后面可以携带参数,规则如下:
参数与路径之间用?分割;
参数键与参数值用=项链;
不同参数用&分隔
代码示例如下:
我们来看一下页面参数,点击左下角的页面路径->页面参数
即可看到:
通过声明式导航传参或编程式导航传参所携带的参数,可以直接在onLoad事件中直接获取到。
比如我刚刚从首页跳转到info过程中传递参数,我在info中的onLoad中打印options:
当我们点击导航按钮,可以在控制台看到参数:
一般情况下都会转存到data节点中,可以用赋值的方法,在data中设置一个query:
接收参数后给query赋值:
页面事件类似于之前学到的按钮事件。
还有一些其他的页面事件,如下拉刷新、上拉触底。本节内容主要介绍的就是下拉刷新与上拉触底。
下拉刷新指通过手指在屏幕上的下拉滑动操作,从而重新加载页面的数据的行为。
小程序默认是没有下拉刷新这种效果的,启用下拉刷新有两种方式:
全局开启下拉刷新:
在app.json这个全局配置文件中,window节点,把enablePullDownRefresh设置为true。(不推荐)
局部开启下拉刷新。
为需要的页面,在该页面的json文件下的window节点中,将enablePullDownRefresh设置为true。
在页面的.js文件中,通过onPullDownRefresh()函数即可监听当前页面的下拉刷新事件。
这里面一般做一些重置操作。
在完成任务后(如重置),调用wx.stopPullDowwnRefresh()可停止当前页面的下拉刷新。
上拉触底,是通过手指在屏幕上的上拉滑动操作,从而加载更多数据的行为。
更多用来实现分页功能。
这个其实是默认开启的。所以我们要做的是监听这个事件,可以调用:onReachBottom()函数来监听。
上拉触底距离指的是触发上拉触底事件时,滚动条距离页面底部的距离。
配置方法,在json文件中:onReachBottomDistanse,后面是数字不需要带单位。
注意,以上的所有,都要开启enablePullD··ownRefresh属性才可以有效果。
做出这样的效果:
可以在帮助中点开微信小程序开发文档看到很多东西。这个的话,可以在数据的请求函数中加上:
当数据请求完成手动取消,与success平级:
节流,简单介绍下,就是在执行一个事情的时候给一个冷却时间,防止一次性执行多次该任务。就类比塔方类游戏,英雄技能需要冷却后才可以使用,不能一次性使用多次。
这里有一篇文章,介绍了防抖与节流:
一文理解防抖与节流
在刷新的时候,经常要做的就是节流处理,如何进行节流处理呢?有以下三个步骤:
->在data中定义isloading节流阀:
false表示当前没有进行任何数据请求;
true表示当前正在进行的数据请求;
->在getColors()方法中修改loading节流阀:
在刚调用getColors时将节流阀设置为true;
在网路请求的complete回调函数中,将节流阀重置为false;
->在onReachBottom中判断节流阀的值,从而对数据请求进行节流控制:
如果节流阀为true,则阻止当前你请求;
如果节流阀为false,则发起数据请求。
生命周期(Life Cycle)是指一个对象从创建->运行->销毁的整个阶段,强调的是一个时间段。
小程序生命周期分为两类,分别是应用生命周期与页面生命周期:
应用生命周期,特指小程序从启动->运行->销毁的过程;
页面生命周期,特指小程序中,每个页面的加载->渲染->销毁的过程。
是由小程序框架提供的内置函数,会伴随着生命周期,自动按次序运行。
生命周期函数:允许程序员在特点的时间点,执行某些特定的操作。例如我们在前面用到的onLoad(页面刚加载时),并且在onLoad中运行一些函数,如发起网络请求。
生命周期强调的是一个时间段,生命周期函数是某个特别的时间点发生的事情。
生命周期函数也分为两类:
应用类生命周期函数,特指小程序从启动->运行->销毁期间依次调用的那些函数
页面生命周期,特指小程序中,每个页面从加载->渲染->销毁期间一次调用的那些函数。
小程序的应用生命周期函数需要在app.js中声明。
onLaunch:小程序初始化完成,执行此函数,全局只触发一次,可以做一些初始化的工作;
onShow:小程序启动,或者从后台进入前台显示时触发;
onHide:小程序从前台进入后台时触发。
这里介绍下前台和后台:当我们在小程序页面时,小程序是在运行的,可以理解为前台;接着说说后台,我们直接退出微信,小程序还没有被关闭,是在后台运行的一个状态,可以理解为后台。
小程序的页面生命周期函数有五个,需要在页面的js文件中进行声明,有以下几个:
onLoad:监听页面加载,一个页面只调用一次;(初始化数据,转存参数)
onShow:监听页面显示;
onReady:监听页面初次渲染完成,一个页面只调用一次;(修改相关样式)
onHide:监听页面隐藏;
onUnload:监听页面卸载,一个页面只调用一次。
WXS(WeiXin Script)是小程序独有的一套脚本语言,结合WXML,可以构建出页面结构。
应用场景:wxml中无法调用在页面.js中定义的函数,但是wxml中可以调用wxs中定义的函数,因此,小程序中的wxs的典型应用场景就是过滤器。
语法类似javaScript,看看区别:
wxs有自己的数据类型:
number数值类型、string字符串类型、boolean布尔类型、object对象类型、function函数类型、array数组类型、date日期类型、regexp正则;
wxs不支持类似于ES6及以上的语法格式:
不支持:let、const、解构赋值、展开运算符、箭头函数、对象属性简写、etc;
支持:var定义变量、普通function函数等类似于Es5的语法。
wxs遵循CommonJS规范:
module对象、require函数、module.exports对象
wxs代码可以编写在wxml文件中的wxs标签内,就像javascript代码可以编写在html文件中的script标签内一样。
每个wxs标签,必须提供module属性,用来指定当前的wxs的模块名称,方便再wxml中访问模块中的成员。
这里来举个例子:
给某个界面加一条数据,姓名是张三,小写的zs:
现在我们想要的是,让zs由小写变为大写呈现在页面上。我们可以在页面中(wxml)嵌入一段wxs:
在上面这段嵌入中,module是必不可少的,是模块的名称,下面必须用module.exports来暴露模块,tdUpper是模块中的函数,被暴露后外部可以调用。
既然已经定义好了,那我们现在来调用即可:
最后可以看到效果:
由上面这个例子可以看出wxs的过滤器效果。
wxs代码还可以编写在以.wxs为后缀名的文件内,就像javascript代码可以编写在以.js为后缀名的文件夹中一样。
先创建一个wxs为后缀的文件,刚刚写的是大写,现在我们来写小写相关的文件:
以上就是一个wxs文件,上面写函数并且return出去,下面把函数暴露出去。注意,wxs中不想js一样支持对象简写,所以下面的暴露需要写完整的键值对写法。
定义完后,可以使用这个脚本。在wxml中,要引入外联的wxs脚本,也要有一个wxs标签,且标签需要由module属性和src属性。
module是用来指定模块的名称;
src用来指定要引入的脚本的路径,且必须是相对路径。
给当前页面新增一条数据:
接着我们在页面上引入外联的脚本:
接着就可以使用啦:
效果如下:
1.wxs与js的关系
为了降低wxs的学习成本,wxs语言在设计时借鉴了大量js的语法,但本质上,wxs与javascript是两种语言。
2.wxs不能作为组件的事件回调
wxs典型的应用场景是过滤器,配合Mustache(模板语法)使用,但是不能作为组件的回调函数!如button中的bindtap后面就不能用到这个。
3.隔离性
wxs运行环境和其他javascript代码是隔离的,体现在:
wxs不能调用js中定义的函数;
wxs不能调用小程序所提供的API;
4.性能好
在IOS设备上,小程序内的WXS会比javaScriipt代码快2-20倍但;
但是在android设备上,二者的运行效率无差异。
第一步,在项目的根目录中,鼠标右键,创建components->test文件夹
第二步,在新建的components->test文件夹上,鼠标右键,点击“新建Component”
第三步,键入组件的名称后回车,会自动生成组件对应的4个文件,后缀名分别为js、json、wxml、和wxss:
引用组件有两种方式,分别是局部引用与全局引用。
在页面的json文件中,引入组件,这是局部引用。
用的时候直接以标签的形式,打个比方我要在home的页面上使用刚刚引入的组件:
如果仅仅是局部引用,则组件只能在引入过该组件的页面使用。
小程序的组件其实与vue组件十分类似。
在全局配置文件app.json中引入:
一旦全局配置,所有的页面都可以使用该组件。
根据组件的使用频率和范围。
如果某组件在多个页面中经常被用到,建议进行”全局引用“
如果某组件只在特定的页面中被用到,建议进行”局部引用"
组件和页面都是由js,json,wxml四个文件组成的,但是,组件和页面的js与json文件有明显不同:
组件的json文件中需要声明:“component” : true 属性;
组件的js文件中调用的是Component()函数;
组件的事件处理函数需要定义到methods节点中。
默认情况下,自定义组件的样式只对当前组件生效,不会影响到组件之外的UI结构,样式其实是有隔离的特性的。
好处:防止外界样式影响组件内部的样式;防止组件的样式破坏外界的样式。
这里说一下组件样式隔离的注意点:
vx的wxss中的全局样式对组件没有影响。
只有class选择器会有样式隔离,id、标签等都没有隔离效果,容易造成样式冲突问题。
如何修改样式隔离:
可以在json中通过stylesolation配置:
"stylesolation": "isolated"//样式隔离
"stylesolation": "apply-shared"//页面wxss样式影响在自定义组件,但自定义组件wxss中指定的样式不会影响界面
"stylesolation": "shared"//组件和页面互相影响
事件处理函数和自定义方法需要定义到methods节点中。
可以先设置一个按钮并给按钮绑定一个事件:
然后再写add的回调:
在小程序组件中,properties是组件的对外属性,用来接收外界传递到组件中的数据。
组件在接收页面传递过来的参数时,需要先对参数进行配置:
有了这层配置,就可从页面传参到组件中了:
在小程序中,data和properties都是可读可写的,但是data更偏向于存储组件的私有数据,properties更倾向于存储外界传递到组件中的数据。
数据监听器:用于监听和响应任何属性和数据字段的变化,从而执行特定的操作,类似于vue中的watch。
监听器:与data平级:observers。
这里来放一段代码,需求是通过监听器获取sum的值:
接着看啊可能一下组件js的写法:
data: {
n1: 0,
n2: 0,
sum: 0
},
observers: {
'n1, n2': function(newn1, newn2) {
this.setData({
sum: newn1 + newn2
})
}
},
/**
* 组件的方法列表
*/
methods: {
addn1() {
this.setData({
n1: this.data.n1 + 1
})
},
addn2() {
this.setData({
n2: this.data.n2 + 1
})
}
}
概念:纯数据字段指的是那些不用于界面渲染的data字段。
好处:纯数据字段有助于提升页面更新的性能。
使用:在Component构造器的options节点中,指定pureDataPattern为一个正则表达式,字段名符合正则表达式则是纯数据字段。
上面这个例子,凡是下划线开头都是纯数据字段:
m是纯数据字段。如果要监听可以在前面加下划线。
生命周期函数 | 描述说明 |
---|---|
created | 在组件实例刚刚被创建时执行 |
attached | 在组件实例进入页面节点树时执行 |
ready | 在组件在视图层布局完成后执行 |
moved | 在组件实例被移动到节点树另一个位置时执行 |
detached | 在组件实例被从页面节点树移除时执行 |
error | 当组件方法抛出错误时执行 |
常用生命周期函数:
created
组件实例刚被创建好的时候,created生命周期函数会被触发;
此时还不能调用setData;
通常在这个生命周期函数中,只应该用于给组件的this添加一些自定义的属性字段
attached
在组件完全初始化完毕,进入页面节点树后,attached生命周期函数会被触发
此时,this.data已被初始化完毕
这个生命周期很欧用,绝大多数初始化的工作可以在这个时机执行(例如发起请求初始数据)
detached
当组件离开页面节点树后,detachedsmzq函数会被触发
退出一个页面时,会触发页面内每个自定义组件的detached生命周期函数
此时适合做一些清理性质的工作
小程序的生命周期函数可以写在Component函数中,也可也再lifetimes字段内进行声明。这是推荐方式,优先级最高。
自定义组件的行为依赖于页面状态的变化,此时就是需要用到组件所在页面的生命周期。
生命周期函数 | 描述 |
---|---|
show | 组件所在的页面被展示时执行 |
hide | 组件所在页面被隐藏时执行 |
resize | 组件所在页面尺寸变化时执行 |
用法:
需要定义在pageLifetimes节点中,接着可以调用以上三个生命周期函数。
自定义组件wxml中,可以提供一个slot节点,用于承载组件使用者提供的wxml结构。
用白话讲一下,就是在组件中放一个坑,在使用组件的页面中去填这个坑。
单个插槽:小程序中,默认每个自定义组件中只允许使用一个slot进行占位,这种个数上的限制叫做单个插槽。
举个例子,先在组件中设置一个坑:
在options中,配置multipleSlots为true,则可以启用多个插槽。
三种方式:
属性绑定:
用于父组件向子组件的指定属性设置数据,仅能设置JSON兼容的数据
事件绑定:
用于子组件向父组件传递数据,可以传递任意数据
获取组件实例:
父组件还可以通过this.selectComponent()获取子组件实例对象
这样就可以直接访问子组件任意数据和方法
属性绑定用于实现父向子传值,而且只能传递普通类型的数据,无法将方法传给子组件。
在父组件中设置要传给子组件的数据:
在子组件的标签中传值:
子组件使用properties节点声明对应属性并使用:
事件绑定
顾名思义就是通过绑定事件来实现。
在父组件的js中,定义一个函数。这个函数将通过自定义事件的形式,传给子组件:
在父组件的wxml中,通过自定义事件的形式,将步骤1中定义的函数引用,传递给子组件(在这一步中要看清楚自定义事件是怎么定义的,前面是bind也就是绑定的意思,sync是自定义事件的名称):
在子组件的js中,通过调用this.triggerEvent('自定义事件名称‘,{/参数对象/},触发自定义事件(第二个事件是需要穿的参数):
在父组件的js中,通过e.detail获取到子组件传递过来的数据:
下面我来给大家讲下逻辑。
我们在父向子传值的时候,父组件把count通过properties声明将值传给了子组件。在父组件中引用子组件可以得到count。
接着我们的目的是,在子组件中让count自增并把结果传给父组件。
在js中可以设置自定义事件,当自定义事件被触发时,可以传递参数,并且自定义事件触发后会有一个回调函数,回调函数会用到之前传递的参数。
结合以上我们分析,在父组件中设置一个自定义事件(注意,是给子组件设置了一个自定义的事件,给谁设置就找谁触发),所以在子组件中触发了该自定义事件,在触发的同时,传递一个参数(回调函数中会用到的参数);当自定义事件被触发后,父组件中会有一个回调函数(意思是自定义事件已经被触发),在这个回调函数中可以接收到子组件传来的参数。于是收到了子组件传来的值,从而实现子向父传值的过程。
可在父组件里调用this.selectComponent("id或class选择器”),获取子组件的实例对象,从而直接访问子组件任意数据和方法,调用时候需要传入一个选择器。
在父组件中,给子组件添加一个类名,并且设置一个按钮,添加一个绑定事件:
接着编辑事件:
效果:
接着就可以对子组件里的数据进行操作了:
注意这里如果对数据进行赋值的话,没办法用this,因为this代表的是当前页面或组件中的数据,这里要用接收到的child。
behaviors是小程序中,用于实现组件间代码共享的特性。这个可以类别vue3中的hook。
如果想要复习可以看下这篇博客:
Vue3中hook的使用及使用中遇到的坑
工作方式:
每个behavior可以包含一组属性、数据、生命周期函数和方法。组件引用它时,它的属性、数据和方法会被合并到组件中。
每个组件中,可以引用多个behavior,behavior也可也引用其他behavior。
首先,在项目根目录下创建一个存放behavior的文件夹
在文件夹里创建第一个behavior:
在这个文件里,创建一个Behavior构造函数的实例对象,内部可以有属性、数据、生命周期函数和方法:
把这个模块暴露出去:
现在就可以导入和使用啦,使用require导入:
小程序中已经支持使用npm第三方的包,从而提高小程序的开发效率,但是,在小程序中使用npm包有以下三个限制:
不支持依赖于Nodejs内置库的包;
不支持依赖于浏览器内置对象的包;
不支持依赖于C++插件的包
横批:为数不多。
是有赞的前端团队开源的一套小程序UI组件库,主力开发者快速搭建小程序应用,所使用的是MIT开源许可证协议,对商业使用比较友好。
类似于element-ui。
官方文档:官方文档链接
在小程序项目中,安装Vant组件库主要分为如下3步:
通过npm安装(建议指定版本为@1.3.3)
构建npm包
修改app.json
第一步:
我们要在终端中来使用npm命令语句,小程序的终端,在开发者工具空白处鼠标点击右键,有一个在外部终端窗口中打开:
先初始化:
npm init -y
注意,这个地方如果报错,极大可能是因为组件名称是中文。组件名称一定要是英文才可以正常使用。
在初始化之后,这个文件有了包管理工具:
第二步:安装vant组件库
npm i @vant/weapp -S --production
第三步:构建npm包
打开微信中的开发者工具->本地设置->点击构建npm并勾选使用npm模块,之后便可以引入组件:
但是在新版本的微信开发者工具中,本地设置中找不到构建npm包了,可在工具中找:
第四步:
修改app.json:将app.json中的"style" : "v2"去除,小程序的新版基础组件强行加上了许多样式,难以去除,不关闭会造成部分样式的混乱:
安装完毕。
安装完Vant组件后,可以在app.json的usingComponents节点中引入需要的组件,即可在wxml中直接使用组件。
比如我们想使用vant提供的button组件:
可以在wxml中正常使用啦:
可以正常使用:
这里如果报错,有两种主要问题:
问题一: 路径不对,可以在新增的@vant文件夹里找到要引入的组件,右键复制相对路径,再更改路径格式;
问题二:报错,找不到相关位置,这种情况一般是因为没构建npm包的原因。如果找不到可以在工具栏中找,这一步是不可以忽略的。
Vant Weapp使用CSS变量来实现定制主题,可以参考官方文档的主题定制,点击链接查看:
具体可以参考官方文档。
上面这个按钮,红色是不是很深,不是很好看。那么这个时候,我们可以定制主题,来修改这个红色。
在app.wxss中,写入CSS变量,即可对全局生效:
几个疑问:
1.为什么使用page节点?
--作用域问题,根节点是page节点。
2.怎么知道变量名?
--官方文档,定制主题,样式变量里面有个配置文件,点开即可。
这里有一篇我之前写的Promise文章,里面详细介绍了Promise的用法及其好处:
前后端交互系列之promise详解
这里不再赘述。
介绍下API Promise化,指的是通过额外的配置,将官方提供的,基于回调函数的异步API,升级改造为基于Promise的异步API,从而提高代码的可读性、维护性、避免回调地狱的问题。
需要依赖于miniprogram-api-promise这个第三方包。
npm i --save [email protected]
小程序中,每安装一个包,都要进行npm构建。因为小程序无法去读node_modules这个包
在构建时,要删除这个文件:
删除后记得保存,保存完毕后,重启,从新编译,基本没有问题。
在小程序中,实现API Promise化主要依赖于miniprogram-api-promise这个第三方的npm包,它的安装和使用步骤如下:
接着就可以使用request,并且夹杂async和await来发起网络请求。
返回值就是一个promise对象。
全局数据共享又叫做状态管理,是为了解决组件之间的数据共享问题。
开啊中常用的数据共享方案有Vuex、Redux、MobX。
在小程序中,可以使用mobx-minprogram来配合moby-miniprogram-bingdings实现全局数据共享,其中:
mobx-miniprogram用来创建Stroe实例对象;
mobx-minprogram-bindings用来把Store中的共享数据或方法,绑定到组件或者页面中去使用。
运行如下命令:
npm i --save [email protected] [email protected]
注意:MobX相关包安装完成之后,记得删除miniprogram_npm目录后,重新 构建npm。
上面这段npm命令最好带版本号。没有版本号可能会报错。
首先,在项目文件夹中创建store:
在store.js中引入相关的包,并且创建构造函数:
在这个构造函数里面,可以把共享的数据挂载进去。
分包是把一个完整的小程序项目,按照需求划分为不同的子包,在构建时打包成不同的分包,用户在使用时按需加载。
分包的好处:
可以优化小程序首次启动的下载时间;
在多团队共同开发的时候可以更好的解耦协作。
分包前后项目构成:
分包前
所有页面(tabBar页面,其他页面)+
公共资源(图片、js脚本、wxs脚本、wxss样式)
分包后
1个主包(启动页面或tabBar页面,以及分包需要用到的公共资源)+
分包(只包含和当期分包有关的页面和私有资源)
在小程序启动时,默认会下载主包并启动主包内页面。
(tabBar页面一定要加载到主包里面)
当客户进入分包的某个页面时,客户端会把对应分包下载下来,下载完成后再进行展示。
(非tabBar页面可以按照功能的不同,分为不同的分包,这就叫做按需下载)
有两个限制:
主包+分包体积不超过16M;
单个分包/主包大小不能超过2M。
否则会发布失败。
以我的为例,这是我的小程序的项目结构,其中,call,home,messages是tabBar页面,要放在主包,info是非tabBar页面,而且不占用公共资源,所以是分包:
现在我在app.json中进行分包的配置。
先配置主包的所有页面:复习一下,主包页面包括tabBar页面以及分包用到的公共资源,这是第一层配置:
接着是分包的配置,主包配置的节点是page,分包配置的节点是subpackages:
其中,root节点是分包的根目录;name是分包的别名;pages里面存放的是根目录下所有页面的相对存放路径。
小程序会按照subpackages的配置进行分包,subpackages之外的目录将被打包到主包中;
主包也可也有自己的pages(最外层的pages字段);
tabBar页面必须在主包内;
分包之间不能相互嵌套。
主包无法引用分包内的私有资源;
分包之间不能相互引用私有资源;
分包可以引用主包内的公共资源。
独立分包的本质是分包,只不过比较特殊的是,独立分包可以独立于主包和其他分包而单独运行。
示意图:
独立分包和主包的区别:是否依赖于主包才能运行:
普通分包必须依赖于主包才能运行;
独立分包可以在不下载主包的情况下,独立运行。
独立分包的应用场景:
开发者可以按需,将某些具有一定功能独立性的页面配置到独立分包中,原因如下:
小程序从普通的分包页面启动时,需要首先下载主包;
而独立分包不依赖主包即可运行,可以很大程度上提升分包页面的启动速度。
配置:
在众多节点下加一个平级的
"independent": true
引用原则
独立分包和普通分包以及主包之间,是相互隔绝的,不能相互引用彼此的资源:
主包无法引用独立分包内的私有资源;
独立分包之间,不能相互引用私有资源;
独立分包和普通分包之间,不能相互引用私有资源;
特别注意:独立分包不能引用主包内的公共资源。
分包预下载指的是在进入小程序的某个页面时,由框架自动预下载可能需要的分包,从而提升进入后续分包页面时的启动速度。
如何配置:
预下载分包的行为,会在进入指定的页面时触发。配置时,在app.json中使用preloadRule节点定义分包的预下载规则:
preloadRule与其他对象属性平级,内部是一个键值对:
内部配置:
其中,第一个地址指的是,进入该页面后进行分包预下载;
packages是必填选项,意思是下载哪个包;
network不是必选,all的意思是不论什么网络都可以分包预下载,如果改成wifi那就是只有网络面膜是是wifi才可以分包预下载。
分包预下载限制:
同一个分包中的页面享有共同的预下载大小限额2M。
如:
到此为止,小程序基础相关的知识已经呈现,我来谈一下我的学习感受。
小程序在我看来,和Vue很相似,并且很多地方也与之前接触到的前端知识吻合。经常听到有人说,小程序很简单很容易上手,真正一套学下来,发现还是很有难度的。
让我觉得学习比较困难的地方是数据共享和分包这一块。在学Vue的时候就觉得数据共享非常繁琐,在小程序中虽然原理上与Vue类似,但是配置发生了改变,所以只是走马观花似的学习;在学习分包这一块,我感到困难并不是因为本身配置有多难,而是没有接触过,所以不理解为什么要这么做。
还是一句话,单凭理论知识的学习,掌握的仅仅只是冰山一角,想要掌握,还需动手做项目,真正的实战实操。
而我之所以写这篇文章的意义,是想记录学习的过程,文章本身比文档更有逻辑性,许久没看,再回顾的时候可以拾起思路,很认真的写下这篇文章,虽然很多都是从老师的课程中拿来的,但是也有很多地方夹杂了我自己的理解,链接了我往期的知识点。所以如果觉得有用,也可也关注收藏一下。而本篇文章的篇幅很长,可能会出现问题,希望大家评论区批评指正。另外有什么这方面的想法或者疑问,也可以评论区或者私信交流。
最后要说,学习是永无止境的,互联网行业的学习,更是不能断的。在这里和大家共勉,希望都能找到好的工作,以及把工作更好的发展延续下去。
后续我还会出一些小程序的其他内容,以及前端甚至架构方面的内容,也可也关注我,我会努力带给您更好的文章!!!