前言:
在文章 一、微信小程序-快速回顾(创建项目、项目结构分析) 中已经提到过,微信小程序的页面需要对应四个文件:
渲染层
页面布局文件 - wxml 和 页面样式文件 - wxss
逻辑层
页面逻辑文件 - js
配置层
页面配置文件 - json
本文的主要目的是对这 4 个文件进行快速回顾
json
文件的内容必须符合 JSON 格式,该文件主要是对页面窗口进行设置,如页面标题、设置页面是否可以下拉、
声明要使用的组件等,这么说可能不够直观,我们用几个案例来感受一下:
通过上面 3 个案例,基本可以了解 json
文件设置后的影响范围,都是对页面窗口进行一些设置,除此之外还可以
指定页面中要使用的组件, 这个本文后面组件部分会介绍
下面列举一些 json
文件中常用的设置,更多请参照 微信小程序页面配置
属性 | 类型 | 默认值 | 描述 |
---|---|---|---|
navigationBarBackgroundColor | 字符(16 进制颜色) | #000000 | 导航栏背景颜色 |
navigationBarTextStyle | 字符 | white | 导航栏标题文字颜色,仅支持 black / white |
navigationBarTitleText | 字符 | Weixin | 导航栏标题文字 |
backgroundColor | 字符(16 进制颜色) | #ffffff | 导航栏下拉时漏出的窗体背景颜色 |
backgroundTextStyle | 字符 | dark | 下拉后,显示的加载图标的颜色,仅支持 dark / light |
enablePullDownRefresh | 布尔 | false | 是否开启当前页面下拉功能 |
微信小程序的页面配置文件,常见格式示例
注意:JSON 格式的文件不能写注释, index.json
:
{
"navigationBarBackgroundColor":"#2ba245",
"backgroundTextStyle":"dark",
"enablePullDownRefresh": true,
"backgroundColor":"#32a4f1"
}
在 js
文件中调用 Page
函数,代表将该目录下同名的的 4 个文件注册为页面文件,Page
函数需要一个对象类型
的参数,该参数对象预定义了一些属性和方法,并会在页面生命周期的各个阶段中分别对这些属性和方法进行回调,
我们可以通过重写这些方法的方法体,在页面生命周期的各阶段实现我们目标效果
下面列举参数对象常用的预定义属性和方法,更多请参照 微信小程序 Page 对象:
类型 | 名称 | 描述 |
---|---|---|
属性 | data | 对象类型,页面中需要使用的数据可以定义为该对象的属性 |
方法 | onLoad(options) | 页面加载时会被回调,如果页面加载后从未被卸载,那么该回调只会执行一次, options 中可以获得 URL 传值 |
方法 | onReady() | 页面渲染完成时会被回调,如果页面加载后从未被卸载,那么该回调只会执行一次 |
方法 | onShow() | 页面显示时会被回调,不管页面是否被卸载过,只要页面切换到显示状态就会被执行该回调 |
方法 | onHide() | 页面状态切换为隐藏时会被回调 |
方法 | onUnload() | 页面卸载时会被回调 |
方法 | onPullDownRefresh() | 用户页面下拉时的回调 |
方法 | onReachBottom() | 用户页面触底时的回调 |
参数对象的 data
属性是一个对象类型,定义在该对象中的属性有与元素绑定的效果( 类似于 Vue 的单向绑定、双
向绑定 ),不需要属性与元素绑定的数据不建议也没必要在此定义
页面显示相关的生命周期函数的执行顺序:
页面加载时: onLoad
→ onShow
→ onReady
,页面被加载过之后未卸载之前只会执行 onShow
微信小程序的页面逻辑文件,常见格式示例
index.js
的 第 5 行 和 第 10 行,是 Page 函数的参数对象预定义的属性和生命周期函数,第 15 行 和 第 18 行 是自
定义的属性和方法,注意:在 Page
函数的参数中,定义的所有属性和方法,互相访问时必须使用关键字 this
:
Page(
// Page 对象参数
{
// 需要属性与元素绑定的数据,要定义在预定义的属性对象 data 中
data: {
name: '这个数据需要属性与元素绑定'
},
// Page 函数的参数对象预定义的生命周期函数 - 页面加载时的回调函数
onLoad(options) {
console.log('预定义的生命周期函数')
},
// 自定义的属性,不需要属性与元素绑定的数据,
temp: '自定义的属性,不需要属性与元素绑定的数据',
// 自定义方法,非预定义的生命周期函数
getInfo() {
console.log('自定义函数')
}
}
);
wxml
文件是用来做页面元素布局的,功能上类似 html
,只不过 wxml
有一套自己的标签和指令,指令就和 Vue
中的指令差不多, 用来做条件渲染、循环等
wxml
的标签非常多,每个标签都有很多的属性,具体使用时一定要参照 微信小程序标签元素,此处列举几个与 html 进行对比:
wxml 元素 | 描述 |
---|---|
view | 独占一行的块级元素,与 html 中的 div 标签一样 |
text | 行内元素,与 html 中的 span 标签一样 |
navigator | 超链接元素,虽然功能与 html 的 a 标签一样,但是 navigator 是块级元素,a 标签是行内元素 |
微信小程序的页面布局文件,常见格式示例
<view>
<view>
个人信息
view>
<view>
<text>姓名:text><text>ares5ktext>
view>
view>
微信小程序的指令 与 Vue
的指令一样,都是以数据为基础,配合各种指令对页面进行渲染,微信小程序的指令不
多,常用的有数据绑定指令:{{}}
、条件指令:wx:if
、循环指令:wx:for
超级简单的语法,只要数据定义在了 js
文件中的 Page
函数的参数对象的 data
属性中,就可以在 wxml
中对数据
使用 mustache 语法,常见使用场景为:数据显示、标签属性赋值,Mustache 语法本身也有表达式计算的能力,
更多使用方式请参考 微信小程序 Mustache 语法
Mustache 语法示例:
1. 在 index.js
中定义数据:
Page({
// 需要属性与元素绑定的数据
data: {
// 布尔类型
isChecked: true,
// 数值类型
age: 27,
// 字符类型
name: 'ares5k'
},
});
2. 在 index.wxml
中使用 mustache 语法:
<checkbox checked="{{isChecked}}">checkbox>
<view>age:{{age}}view>
<view>name:{{'姓名' + name}}view>
条件指令 wx:if
用来进行布尔判断,常作为标签属性,只有条件满足时标签才会被渲染,可以与 wx:elif
以及
wx:else
搭配使用,更多使用方式请参考 微信小程序条件指令
微信小程序中,标签的 hidden
属性也可以让元素不显示,但 hidden
属性和 wx:if
指令是有本质的区别的,添加
hidden
属性的标签会出现在文档流中,只不过隐藏了,而 wx:if
是不满足条件的元素,压根就不会出现在文档流中
wx:if 语法示例:
1. 在 index.js
中定义数据:
Page({
// 需要属性与元素绑定的数据
data: {
// 布尔类型
isChecked: true
}
});
2. 在 index.wxml
中使用 wx:if
进行条件判断:
<view wx:if="{{isChecked}}">
单独使用 wx:if,布尔表达式为真,显示该内容
view>
<view wx:if="{{!isChecked}}">
搭配 wx:else 使用,布尔表达式为真,显示该内容
view>
<view wx:else>
搭配 wx:else 使用,布尔表达式为假,显示该内容
view>
对数组或者对象进行遍历的时候,可以使用 wx:for
指令,wx:for
指令也是标签属性,与其常一同出现的指令还有
wx:for-item
、wx:for-index
、wx:key
,下面简单对它们进行描述,更多请参考 微信小程序循环指令
属性名 | 描述 |
---|---|
wx:for | 用来遍历数组或对象 |
wx:item | 给循环项设置变量名. 默认名为 item,当遍历数组时, item 为本次遍历的数组元素,当遍历对象时, item 为本次遍历的属性值 |
wx:index | 给循环项设置变量名. 默认名为 index,当遍历数组时, index 为本次遍历的下标索引,当遍历对象时, index 为本次遍历的属性名 |
wx:key | 指定遍历项中的唯一属性,当遍历的数组动态添加元素时,可以提升渲染性能,也能正确保存之前的输入值或状态值 |
1. 遍历数组示例
(1) 在 index.js
中添加数组数据
Page({
// 需要属性与元素绑定的数据
data: {
// 普通数组
stillArray: ['h5c3', 'vue', 'miniprogram'],
// 对象数组
phoneObjArray: [{
name: 'huawei nova9',
price: 2600
},
{
name: 'iphone13 pro',
price: 8900
}
]
}
});
(2) 在 index.wxml
中使用 wx:for
对数组进行遍历
<view>遍历普通数组:view>
<view wx:for="{{stillArray}}">
数组下表为:{{index}},对应的值为:{{item}}
view>
<view wx:for="{{stillArray}}" wx:for-item="content" wx:for-index="contentIndex">
数组下表为:{{contentIndex}},对应的值为:{{content}}
view>
<view style="margin-top:50rpx;">遍历对象数组:view>
<view wx:for="{{phoneObjArray}}">
数组下表为:{{index}} 的电话名称是:{{item.name}}
view>
<view wx:for="{{phoneObjArray}}" wx:for-item="phone" wx:for-index="phoneIndex">
数组下表为:{{phoneIndex}} 的电话名称是:{{phone.name}}
view>
2. 遍历对象数组示例
(1) 在 index.js
中添加对象数据
Page({
// 需要属性与元素绑定的数据
data: {
// 对象
address: {
province: '辽宁',
city: '大连'
}
}
});
(2) 在 index.wxml
中使用 wx:for
遍历对象
<view wx:for="{{address}}">
对象属性名为:{{index}},对应的值为:{{item}}
view>
<view wx:for="{{address}}" wx:for-item="value" wx:for-index="name">
对象属性名为:{{name}},对应的值为:{{value}}
view>
3. wx:key
前面两个示例的运行效果图中,在控制台都有黄色的警告弹出,这是因为 wx:for
没有搭配 wx:key
指令属性使用,
wx:key
的原理和作用与 Vue
中的 :key
差不多,都是为了提升渲染性能和保存标签状态,具体原理请参照本人 Vue
系
列文章中对 :key
的记载,本文只是简单讨论和演示一下它的作用
由于 wx:for
机制的原因,当我们动态改变数组的内容,或变换数组元素的顺序时,以该数组为基础遍历出来的表单
标签的状态会发生错乱(标签状态比如 输入框的值,复选框是否选中等),我们来做个实验:
未使用 wx:key
,修改数组内容时的表单效果
上面动图中可以看到,当在数组的最开头动态添加元素,从而改变数组中元素的顺序时,原本输入过的值就会发生
错乱,我们现在添加 wx:key
看看效果, wx:key
属性的取值有以下 3 种情况:
wx:key
wx:key
赋值为 *this
wx:key
通过使用 wx:key
前后的动图对比,能够很容易理解 wx:key
对于表单标签状态错乱的作用
wx:key
还有个提升渲染性能的特点,其实上面两张动图也能很好的表现出来,先看未使用 wx:key
的动图,当点击
<加一个> 按钮后,右下角控制台的代码中,所有基于数组循环出来的标签都会紫色高亮一下,这代表他们在重新渲染,
而使用 wx:key
的动图中,并不是所有的标签都高亮显示,因为只有新增的标签才会渲染,原本已有的标签不受影响
block
标签是一个结构块,在项目真正运行时不会输出到文档流中,一般用来搭配条件指令和渲染指令使用,可以
使代码结构更清晰,又不影响实际运行时的层级
1. 假设 wxml
中有如下代码:
<view>
1
view>
<view>
2
view>
<view>
3
view>
2. 现在希望这段代码在满足条件时才输出,我们一般的做法是在最外层在套一个
并和 wx:if
指令搭配:
<view wx:if="{{1==1}}">
<view>
1
view>
<view>
2
view>
<view>
3
view>
view>
3. 但是上面这种修改方式的缺点很明显, 就是改变了我们的层级,所以为了不改变层级,还可以这样修改:
<view wx:if="{{1==1}}">
1
view>
<view wx:if="{{1==1}}">
2
view>
<view wx:if="{{1==1}}">
3
view>
4. 上面的这种改法也有很明显的缺点,就是写了太多遍重复的 wx:if
指令,后期维护也不方便
对于这种情况,就非常适合使用
标签:
<block wx:if="{{1==1}}">
<view>
1
view>
<view>
2
view>
<view>
3
view>
block>
5. 使用 block
标签后,虽然看起来改变了层级,但是通过实际运行后的代码能看出,文档流中并没有 block
标签:
wxss
是页面样式文件,功能和 CSS 一样,CSS 语法也几乎都支持,所以没有太多需要回顾的,此处只回顾一
下 wxss
中新增的响应式像素单位 rpx
和 样式文件导入
使用 rpx
当作尺寸单位会有响应式的效果,当屏幕宽度变化时,其会等比例伸缩
先来对比一下和 px
的区别:
(1) 使用 px
为盒子的尺寸单位,将屏幕宽度调整后,盒子的大小不变
(2) 使用 rpx
为盒子的尺寸单位,屏幕宽度后,盒子大小等比例变换
尺寸单位换算
细心的可以发现,上面两个动图中,最初都是在 iphone6 上显示尺寸为 300 的盒子, 但是因为尺寸单位不一样,
导致实际显示大小也不一样,那问题就来了,比如设计稿就是以 iphone6 的宽度设计的,其要求显示 300 px
大小的盒子,
那么应该怎么能知道对应的 rpx
值呢?
这其实涉及到换算问题,一般设计稿中的尺寸都是以 px
为单位,如果想将尺寸单位换成 rpx
,是需要进行一些简
单计算的,微信小程序规定屏幕宽度为 750rpx
,这个规定的意思是说,不管屏幕实际的宽度是多少 px
,在微信小程
序中均为 750rpx
通过这个规定,我们可以得到换算公式:750rpx = Npx
也就是说 1rpx = N/750px
,现在套用这个公式计算一下
设计稿中要求的 300px
的盒子在 iphone6 中到底应该是多少 rpx
,iphone 6 屏幕的实际宽度是 375px
,
那么 750rpx = 375px
→ 2rpx = 1px
-> 600rpx = 300px
,最后推算出在 iphone6 中应该是 600rpx
计算后,对比 600rpx
的盒子和 300px
的盒子的大小,完全没区别:
当我们想导入其他样式文件时,可以在页面的样式文件中使用 @import 相对路径
的方式引入