小程序模板语法
目录
1.1双向绑定
1.2 列表渲染
1.3 条件渲染
生命周期
2.1 应用级别的生命周期
2.2 页面级别的生命周期
内置 API
3.1 网络请求
3.2 界面交互
3.3 本地存储
npm 支持
4.1 默认构建
4.2 自定义构建
修改小程序的根目录
手动 npm 构建小程序
在小程序中使用 vant 组件库
步骤一 通过 npm 安装
步骤二 修改 app.json
步骤三 修改 project.config.json
步骤四 构建 npm 包
步骤五 使用
小程序有一套专门的模板语法来实现数据的渲染。
1.1双向绑定
小程序支持数据双向绑定,语法如下所示:
pages/index/index.wxml
<view>{{ msg }}</view>
<input name="number" model:value="{{ msg }}" />
pages/index/index.js
Page({data: {msg: 'hello mp'}
})
pages/index/index.wxss
input {height: 40px;padding: 0 10px;margin: 10rpx 0;
}
注意双向绑定仍然采用插值语法
微信小程序中 input
、textarea
、checkbox
等表单组件都支持双向绑定语法。
1.2 列表渲染
如果 data 中有一个数组类型的列表数据,我们要如何渲染出来呢? 小程序提供了一个指令 wx:for
类似于 Vue 中的 v-for
,通过一个小例子来学习:
pages/index/index.js
// 调用 Page 函数
Page({data: {students: [{ id: 1, name: '小明', age: 18, gender: '男' },{ id: 2, name: '小红', age: 17, gender: '女' },{ id: 3, name: '小刚', age: 19, gender: '男' },{ id: 4, name: '小丽', age: 18, gender: '女' },{ id: 5, name: '小米', age: 19, gender: '女' }]}
})
基本的语法格式
wx:for
的语法格式为 wx:for="{{ 数据名称 }}"
,并且内置默认通过 index
获取数组的索引值,item
访问数组的单元值,如下代码所示:
pages/index/index.wxml
<view class="students"><view class="item"><text>序号</text><text>姓名</text><text>年龄</text><text>性别</text></view><view class="item" wx:for="{{students}}"><text>{{index + 1}}</text><text>{{item.name}}</text><text>{{item.age}}</text><text>{{item.gender}}</text></view>
</view>
样式美化:
pages/index/index.wxss
.students {margin-top: 10px;margin-bottom: 10px;border: 1px solid #ccc;border-right: none;border-bottom: none;
}.students .item {display: flex;justify-content: space-evenly;text-align: center;line-height: 30px;
}.students .item:first-child {background-color: #eee;
}.students text {flex: 1;border-right: 1px solid #ccc;border-bottom: 1px solid #ccc;
}
wx:key
在使用 wx:for
时会收到一个警告
是由于在使用 wx:for
时没有指定 wx:key
属性,这个 wx:key
属性的作用于 Vue 中一样的,但是语法稍有不同,大家一定要注意,如下所示:
pages/index/index.wxml
<view class="students"><view class="item"><text>序号</text><text>姓名</text><text>年龄</text><text>性别</text></view><view class="item" wx:for="{{students}}" wx:key="id"><text>{{index + 1}}</text><text>{{item.name}}</text><text>{{item.age}}</text><text>{{item.gender}}</text></view>
</view>[{id: xx, name},{}]
*this:
上述代码中 wx:key
属性的值要求必须具有唯一性,使用时分成两种情形:
-
数组单元是对象类型时,只要写对象的属性名
-
数组单元为简单类型数据时,使用
*this
指定为wx:key
的值
pages/index/index.js
Page({data: {names: ['小明', '小红', '小刚', '小丽', '小米']}
})
pages/index/index.wxml
<view class="students"><view class="item"><text>序号</text><text>姓名</text></view><view class="item" wx:for="{{names}}" wx:key="*this"><text>{{index + 1}}</text><text>{{item}}</text></view>
</view>
自定义单元值和索引值的名字
开发中 wx:for
的嵌套是比较常见的,外层 wx:for
和内层的 wx:for
都使用 index
和 item
来访问数组的索引和单元,会使得代码的易读性比较差,这种情况下通过 wx:for-index
和 wx:for-item
来分别指定如何访问数组的索引值和单元值,如下代码所示:
pages/index/index.wxml
<view class="students"><view class="item"><text>序号</text><text>姓名</text><text>年龄</text><text>性别</text></view><view class="item" wx:for="{{students}}" wx:key="id" wx:for-index="key" wx:for-item="student"><text>{{key + 1}}</text><text>{{student.name}}</text><text>{{student.age}}</text><text>{{student.gender}}</text></view>
</view>
1.3 条件渲染
wx:if
通过条件渲染控制元素或组件的显示与隐藏
pages/index/index.js
// 调用 Page 函数
Page({data: {show: true},toggle() {// 切换 show 的值this.setData({show: !this.data.show})}
})
pages/index/index.wxml
<!-- 条件数据渲染 -->
<button type="primary" bind:tap="toggle">显示/隐藏</button>
<view wx:if="{{show}}">{{msg}}</view>
hidden
除了使用 wx:if
来控制元素的显示外,还可以使用 hidden
属性来实现相同的结果
pages/index/index.wxml
<!-- 条件数据渲染 -->
<button type="primary" bind:tap="toggle">显示/隐藏</button>
<view hidden="{{!show}}">{{msg}}</view>
对比 wx:if
和 hidden
二者的区别:
-
wx:if
在条件为true
时会将内容渲染出来,否则不会进行渲染,是通过【添加/删除】节点的方式来实现的。 -
hidden
在条件为true
时会隐藏内容,否则会显示内容,是通过display
样式属性来实现的。
wx:else
pages/index/index.js
// 调用 Page 函数
Page({data: {isLogin: false}
})
pages/index/index.wxml
<view wx:if="{{isLogin}}">完善用户信息</view>
<view wx:else>请先登录</view>
block
block
是小程序中一个特殊的标签,起到包裹的作用,不会生成真实的元素,类似于 vue 中的 template 标签。
需求:假如有一个列表数据需要渲染,我们要求只有列表的长度大于 0 时才渲染,否则给用户一个提示信息。
pages/index/index.wxml
<block wx:if="{{isLogin}}"><view class="msg">{{msg}}</view><input name="number" value="{{number}}" /><!-- 列表数据渲染 --><view class="students">...</view><!-- 条件数据渲染 --><button type="primary" bind:tap="toggle">显示/隐藏</button><view wx:if="{{show}}">{{msg}}</view><view hidden="{{!show}}">{{msg}}</view><view wx:if="{{isLogin}}">完善用户信息</view><view wx:else>请先登录</view>
</block><view wx:else>空空如也~</view>
生命周期
我们都知道生命周期是一组名称固定且会自动执行的函数,在开发小程序时也有专门的的生命周期函数,分为下面 3 种类型:
-
应用级别
-
页面级别
-
组件级别
2.1 应用级别的生命周期
应用级别的生命周期是针对小程序整体而言,定义在 app.js
当中,且生命周期函数的名称及执行情况如下表所示
app.js
:里面必须调用内置的全局函数 App
,并传入一个 {}
参数
App({// 只会执行 1 次// 用户在点击右上角的胶囊关闭小程序时,小程序并未被关闭,只是将小程序置于后台运行了。因此小 onLaunch 并不会重复执行。// 当小程序执行停留在后台约 5 分钟、关机、小程序都会自动被关闭。再次打开小程序时 onLaunch 会再次被执行。onLaunch() {console.log('小程序启动了!')},// 会反复执行onShow() {console.log('小程序处于前台状态!')},// 会反复执行onHide() {console.log('小程序处于后台状态!')}
})
通过应用级别的生命周期可以进行一些全局性的设置,如检测用户的登录状态(后期项目中会用到)、获取小程序的场景值等。
场景值
所谓的场景描述的是用户打开小程序的方式,如扫码、搜索、分享等,并且每个场景都对应了一个数值,即场景值,根据这个场景值来判断用户打开小程序的方式,进而分析用户的行为,常见的场景值如下表所示:
获取小程序的声景值只能在全局生周期函数 onLaunch
、onShow
中获取,代码如下所示
app.js
App({onLaunch(params) {console.log(params.scene)},onShow(params) {console.log(params.scene)}
})
获取到场景值后就可以确定用户是以何种方式打开小程序了,进而分析用户的行为,帮助管理者制订合理的营销方案。
举例说明:比如通过场景值发现最近一段时间大量用户是通过分享的方式打开小程序的,那说明用户分享的意愿很强,营销活动有成效,如果用户主动去搜索小程序,说明小程序的知名度和受欢迎程序都比较高等
2.2 页面级别的生命周期
页面级别的生命周期函数是针对某个页面而言,写在页面对应的页面 .js
当中
基本语法
想要为哪个页面添加生命周期,就在哪个页面对应的 js 文件中写相应的生命周期函数
以首页的 .js
为例演示用法:
pages/index/index.js
Page({// 最先执行(只会执行一次)onLoad() {console.log('页面加载完成...')},// 其次执行(会反复执行)onShow() {console.log('页面显示完成...')},// 第三执行(只会执行一次)onReady() {console.log('页面渲染完成...')},// 会反复执行// 演示:使用一个链接跳转到 logs 页面onHide() {console.log('页面隐藏了...')},// 普通链接跳转及切换 Tab 页面不会卸载,页面处理隐藏的状态,所以页面被卸载的生命周期不会被执行// 在学习 redirectTo 时演示onUnload() {console.log('页面即将卸载...')}
})
获取地址参数
小程序在进行页面跳转时可以在跳转地址上通过 ?
来拼凑参数,这些参数只能通过 onLoad
生命周期函来获取,用法如下所示:
我们在首页面添加一个链接使其跳转到 logs
页面,并且在地址上通过 ?
来拼凑一些参数
page/index/index.wxml
<navigator url="/pages/logs/logs?name=小明&age=18">跳转到日志页面</navigator>
在 logs
页面中,获取地址上的参数,代码如下所示:
page/logs/logs.js
Page({data: {name: '',age: '',},onLoad(query) {// 查看地址中的参数console.log(query)// 记录存储地址参数this.setData(query)},
})
pages/logs/logs.wxml
<view>姓名: {{name}} 年龄: {{age}}</view>
小技巧:小程序开发者工具提供了关于地址参数及页面路径的调试方法,如下图所示:
内置 API
小程序 API 是小程序内置提供的一系列的方法,通过这些方法能够实现很多的功能,比如网络请求、本地存储、微信支付、拍照、扫码等,这些 API 通过全局对象 wx
进行调用。
3.1 网络请求
学习内容
-
发起请求方法的使用
-
设置合法域名
wx.request
API 是用来发起网络请求的,类似于网页中的 ajax
,其用法如下所示:
// 小程序发起网络请求(调用接口)的方法
wx.request({// 接口地址url: 'api/path/xxx',// 请求的方法method: 'GET|POST|PUT',// 请求时的数据data: {},success: (res) => {// 成功的回调},fail: () => {// 失败的回调},complete: () => {// 请求结束的回调},// ...
})
获取学生列表数据
pages/index/index.js
Page({onLoad() {// 页面加载完成即获取学生列表this.getStudentList()},// 获取学生列表数据getStudentList() {// 调用小程序 apiwx.request({url: 'https://mock.boxuegu.com/mock/3293/students',method: 'GET',success: (res) => {console.log(res)}})}
})
上述代码的执行时会报告一个错误,如下图:
小程序规定 wx.request
调用接口的服务器地址(域名)必须事先在小程序的管理后台进行设置,否则是不允许发起网络请求,如何解决这个问题呢?有两种方式:
-
在小程序管理后台进行设置
-
在小程序开发工具中进行设置
-
管理后台设置步骤:开发管理 => 开发设置 => 服务器域名 => 开始配置
注意:
域名有个严格的要求:必须是
https
协议且已备案!
-
在开发工具中设置步骤如下
注意:
在开发工具中设置的方式只适用于开发环境,即只能在小程序开发者工具中生效。
渲染学生列表数据
pages/index/index.js
Page({onLoad() {// 页面加载完成即获取学生列表this.getStudentList()},// 获取学生表表getStudentList() {// 调用小程序 apiwx.request({url: 'https://mock.boxuegu.com/mock/3293/students',method: 'GET',success: (res) => {this.setData({students: res.data.result})}})}
})
3.2 界面交互
小程序还提供了一些用于界面交互的 API,如加载提示、信息反馈、确认框等。
加载提示
加载提示框常配合网络请求来使用,用于增加用户体验,对应的 API 有两个,分别为:
-
wx.showLoading
显示加载提示框 -
wx.hideLoading
隐藏加载提示框
它们的语法如下:
// 显示加载提示
wx.showLoading({title: '正在加载...',mask: true,
})
// 隐藏加载提示
wx.hideLoading()
结合上一节获取学生列表来演示这两个 API 的使用:
pages/index/index.js
Page({// 获取学生表表getStudentList() {// 显示提示框wx.showLoading({title: '正在加载...',mask: true})// 发起请求wx.request({url: 'https://mock.boxuegu.com/mock/3293/students',method: 'GET',// 这里注意因为 this 的原因,推荐使用箭头函数success: (res) => {this.setData({// 更新 students 数组students: res.data.result})},complete() {// 隐藏提示框wx.hideLoading()}})}
})
在调用 wx.showLoading
时可以传入以下参数:
-
title
指定显示的文字提示内容(不能省略) -
mask
提供一个透明层阻止对页面其它内容进行操作 -
success
显示加载提示框成功后的回调(很少用到) -
fail
显示加载提示框失败后的回调(很少用到) -
complete
显示加载提示框完成后的回调(包括成功和失败两种情况)
信息提示
信息反馈是指根据用户的某些操作来告知操作的结果,如用户点击加入购物车,提示用户添加成功,用户提交表单提示用户表单验证的结果等,对应的 API 是 wx.showToast
其语法如下:
wx.showToast({title: '操作成功',duration: 2000,mask: true,icon: 'success'
})
以表单验证举例说明 API 的使用:
pages/index/index.wxml
<!-- 省略了部分代码 -->
<input type="text" model:value="{{username}}" placeholder="请填写您的姓名" />
<button type="primary" bind:tap="submitForm">提交</button>
pages/index/index.js
Page({data: {username: ''},submitForm() {// 验证姓名只能为汉字const reg = /^[\\u4e00-\\u9fa5]{2,5}$/;// 验证结果const valid = reg.test(this.data.username.trim())// 提示验证结果if (!valid) {wx.showToast({title: '姓名只能为2到5位汉字!',mask: true,icon: 'error'})return}// 校验通过后的逻辑}
})
在调用 wx.showToast
时可以传入以下参数:
-
title
指定显示的文字提示内容(不能省略) -
mask
提供一个透明层阻止对页面其它内容进行操作 -
icon
指定图标类型 -
duration
指定信息反馈的显示时长 -
success
信息反馈成功后的回调(很少用到) -
fail
信息反馈失败后的回调(很少用到) -
complete
信息反馈完成后的回调(包括成功和失败两种情况)
3.3 本地存储
基本用法
小程序中也能够像网页一样支持本地存储数据,用于在本地存一些数据,比如用户登录状态 token 等,其包含以下 4个主要的 API:
-
wx.setStorageSync
在本地存入一个数据 -
wx.getStorageSync
读取本地的一个数据 -
wx.removeStorageSync
删除本地存储的一个数据 -
wx.clearStorageSync
清空本地存储的数据
pages/index/index.wxml
<button type="primary" bind:tap="setStorage">添加本地数据</button>
<button type="primary" bind:tap="getStorage">获取本地数据</button>
<button type="primary" bind:tap="removeStorage">删除本地数据</button>
<button type="primary" bind:tap="clearStorage">清空本地数据</button>
pages/index/index.js
Page({// 存入本地数据setStorage() {wx.setStorageSync('name', '小明')// 可以直接存入对象类型数据,无需使用 JSON.stringify 处理wx.setStorageSync('user', { name: '小明', age: 18 })},// 读取本地数据getStorage() {const name = wx.getStorageSync('name')// 对象类型的数据不必 JSON.parse 处理const user = wx.getStorageSync('user')},// 删除本地数据removeStorage() {wx.removeStorageSync('name')},// 清空本地数据clearStorage() {wx.clearStorageSync()}
})
异步版本的 API
-
wx.setStorage
在本地存入一个数据 -
wx.getStorage
读取本地的一个数据 -
wx.removeStorage
删除本地存储的一个数据 -
wx.clearStorage
清空本地存储的数据
调用异步方式的 API 传入的是一个对象类型的参数:
pages/index/index.js
Page({// 存入本地数据setStorage() {wx.setStorage({key: 'token',data: 'fajkfloweijgvnsloruj'})},// 读取本地数据getStorage() {wx.getStorage({key: 'token',success(res) {console.log(res.data)}})},// 删除本地数据removeStorage() {wx.removeStorage({key: 'token',success (res) {console.log(res)}})},// 清空本地数据clearStorage() {wx.clearStorage()}
})
提示:
在小程序中
Sync
结尾的 API 指的是同步方式执行,同步方式执行的 API 在使用时简洁比较好,但缺点是同步会阻塞程序执行,执行效率上相较异步版本要差一些。
npm 支持
4.1 默认构建
小程序不能直接使用 npm 下载的第三方包,必须经过小程序开发者工具进行构建后才可以使用,这一节我们来学习支持 npm 的步骤:
-
安装 npm 包:在终端命令行中,安装想用的第三方包
-
构建 npm 包:工具 => 构建 npm。
构建成功之后,会生成一个 miniprogram_npm 的文件夹。这里存放的就是小程序构建后的 npm 包。这样就可以在小程序中使用 npm 的第三方包了。
1. 打开终端窗口,安装一个 npm 模块包,以 miniprogram-computed
为例
安装 miniprogram-computed
# 安装 miniprogram-computed
npm install miniprogram-computed
这一步操作是与以往的 npm 模块安装没有任何的区别,会将模块安装到 node_modules
当中,但是下载的模块无法直接导入到小程序中,如下图所示:
2. 构建 npm,步骤如下图所
构建 npm 的结果会创建一个新的目录 miniprogram_npm
,然后自动把构建后的 npm 模块放到了这个目录之下。
此时在小程序中便可以成功导入 npm 的模块包了。
miniprogram-computed 使用
pages/index/index.js
// 导入构建后的 npm 模块
const computedBehavior = require('miniprogram-computed').behavior
Page({// 将其应用到页面中behaviors: [computedBehavior],data: {n1: 1,n2: 1,},computed: {sum(data) {return data.n1 + data.n2}}
})
pages/index/index.wxml
<view>n1 + n2 = {{ sum }}</view>
4.2 自定义构建
修改小程序的根目录
在实际开发中,为了更好的管理项目的代码,会将小程序相关的内容单独放到一个文件夹中去维护,这样做的好处是能够优化目录结构(公司的项目目录都是优化过的)。比如:
-
新建
miniprogram
文件夹 -
将
pages
utils
app.js
app.json
app.wxss
sitemap.json
移动到miniprogram
文件夹中 -
小程序运行时,会自动寻找根目录下的
app.json
,但此时app.json
已经不在根目录中了,所以会报错。 -
所以我们需要修改小程序的根目录。
project.config.json
{"miniprogramRoot": "./miniprogram"
}
修改完小程序的根目录之后,就找不到 npm 包的内容了,所以会报错。
手动 npm 构建小程序
引起找不到 npm 包的原因:
当前,默认构建后的 npm 和小程序的代码不在同一个目录中。那么小程序的代码就找不到对应的 npm
包了,项目就会报错。
所以开启手动构建,目的是让构建后的 npm 和小程序的代码在同一个目录中。
手动构建需要修改如下配置:
-
packNpmManually
:启用 npm 手动构建 -
packNpmRelationList
:手动构建 npm 配置详情-
packageJsonPath
:找到 package.json,按照这个文件里面记录的安装包去构建。 -
miniprogramNpmDistDir
:构建之后的结果放在哪
-
project.config.json
再次使用 工具 => 构建 npm 一次,之前用到的 npm 包,又可以继续使用了
在小程序中使用 vant 组件库
步骤一 通过 npm 安装
步骤二 修改 app.json
将 app.json 中的 "style": "v2"
去除,小程序的新版基础组件强行加上了许多样式,难以覆盖,不关闭将造成部分组件样式混乱。
步骤三 修改 project.config.json
开发者工具创建的项目,miniprogramRoot
默认为 miniprogram
,package.json
在其外部,npm 构建无法正常工作。
需要手动在 project.config.json
内添加如下配置,使开发者工具可以正确索引到 npm 依赖的位置。
步骤四 构建 npm 包
打开微信开发者工具,点击 工具 -> 构建 npm,并勾选 使用 npm 模块 选项,构建完成后,即可引入组件。
注意:如果构建失败,可以清除缓存再次构建
步骤五 使用
引入组件