创建小程序项目
输入 AppID ,选择不使用云服务,模版类型为 JavaScript 基础模版
小程序目录结构
pages
用于存放小程序所有页面,每个页面以单独的文件夹存在
.js 文件:
当前页面的脚本文件,存放页面逻辑、数据、事件处理函数等
.json 文件:
当前页面的配置文件,配置当前页面的窗口外观。页面中的配置项会覆盖 app.json 的 window 中相同的配置项。
JSON 是一种数据格式,在实际开发中,JSON 总是以配置文件的形式出现。小程序项目中也不例外,通过不同的 .json 配置文件,可以对小程序项目进行不同级别的配置
wxml 文件:
当前页面的模版结构文件
wxss 文件:
当前页面的样式表文件
utils
用于存放工具性质的模块
app.js
小程序项目的入口文件
app.json
小程序项目的全局配置文件,包含了小程序的所有页面路径、窗口外观、界面表现、底部tab等。
- pages:记录当前小程序所有页面的路径
- window:全局定义小程序所有页面的背景色、文字颜色、窗口等
- tabbar:设置小程序底部的 tabbar 效果
- style:全局定义小程序组件所使用的样式版本,v2 表示最新的版本
- sitemapLocation:指明 sitemap.json 的位置
app.wxss
小程序项目全局样式文件
project.config.json
项目的配置文件。用于记录我们对小程序开发工具所做的个性化配置,如 setting 里保存了在小程序详情里的设置选项
sitemap.json
用于配置小程序及其页面是否允许被微信索引。
* allow 表示页面允许被索引,disallow 则不允许
* 在终端里通常会报告警告页面是否会被索引,如果需要取消警告信息,可以在 project.config.json 的 setting 中将 checkSiteMap 改为 false
小程序的宿主环境
https://www.bilibili.com/video/BV1834y1676P?p=7
宿主环境 ( host environment ) 指的是程序运行所必须的依赖环境。手机微信是微信小程序的宿主环境。
包含内容
- 通信模型
- 运行机制
- 组件
- API
通信模型
小程序中通信的主体是渲染层和逻辑层:
- WXML 模板和 WXSS 样式工作在渲染层
- JS 脚本工作在逻辑层
小程序中的通信模型分为两个部分,两部分都是由微信客户端进行转发:
- 渲染层和逻辑层之间的通信
- 逻辑层和第三方服务器之间的通信
运行机制
启动过程
- 将小程序的代码包下载到本地
- 解析 app.json 全局配置文件
- 执行 app.js 小程序入口文件,调用 App() 创建小程序实例
- 渲染小程序首页
- 小程序启动完成
页面渲染过程
- 加载并解析页面的 .json 配置文件
- 加载页面 .wxml 和 .wxss
- 执行页面的 .js 文件,调用 Page() 创建页面实例
- 页面渲染完成
全局配置
window
配置小程序的顶部导航栏以及背景
- navigationBarTitleText:导航标题文字内容
- navigationBarBackgroundColor:导航栏背景颜色,仅支持 16 进制颜色
- navigationBarTextStyle:导航标题颜色,仅支持 black / white
- backgroundColor:窗口背景色,仅支持 16 进制颜色
- backgroundTextStyle:下拉 loading 样式,仅支持 dark / light
- enablePullDownRefresh:是否全局开启下拉刷新
- onReachBottomDistance:页面上拉触底事件触发时距页面底部距离,单位 px,默认为 50
tabBar
小程序中通常分为两种 tabBar,底部 tabBar 和顶部 tabBar,tabBar 中只能配置最少2个,最多5个tab页标签,当渲染顶部 tabBar 时,不显示icon,只显示文本。
TabBar 的6个组成部分:
- backgrounColor:背景色
- borderStyle:上边框颜色
- iconPath:未选中时的图片路径
- color:未选中时的文字颜色
- selectedIconPath:选中时的图片路径
- selectedColor:选中时的文字颜色
TabBar 节点的配置项
- position:仅支持 bottom / top
- borderStyle:上边框颜色,仅支持 black / white
- color:未选中时文字颜色
- selectedColor:选中时文字颜色
- backgroundColor:背景色
- list ( 必填 ):tab页标签列表,最少2个,最多5个
- pagePath ( 必填 ):页面路径,必须在 pages 中预先定义
- text ( 必填 ):文字内容
- iconPath:未选中时图片路径
- selectedIconPath:选中时图片路径
"tabBar": {
"list": [
{
"pagePath": "pages/index/index",
"text": "首页"
},
{
"pagePath": "pages/list/list",
"text": "列表"
}
]
}
页面
新建页面
在 app.json -> pages 中新增页面的存放路径,小程序开发工具即可自动创建对应的页面文件夹以及相关文件。
// 新增 list 页面
"pages":[
"pages/index/index",
"pages/logs/logs",
"pages/list/list"
],
修改项目首页
只需要调整 app.json -> pages 数组中页面路径的前后顺序,即可修改项目首页。小程序会把排在第一位的页面,当作项目首页进行渲染
// 将 list 页面设置为首页
"pages":[
"pages/list/list",
"pages/index/index",
"pages/logs/logs"
],
WXML
WXML ( WeiXin Markup Language ) 是小程序框架设计的一套标签语言,用来构建小程序页面的结构,其作用类似于网页开发中的 HTML。
WXML 和 HTML 的区别
标签名称不同
- div -> view
- span -> text
- img -> image
- a -> navigator
属性节点不同
- href -> url
提供了类似 Vue 中的模板语法
- 数据绑定
- 列表渲染
- 条件渲染
WXSS
WXSS ( WeiXin Style Sheets ) 是小程序中的样式语言,用于描述 WXML 的组件样式,类似于网页开发中的 CSS。
WXSS 和 CSS 的区别
- 新增了 rpx 尺寸单位,可以在不同大小屏幕上小程序会自动进行换算,类似于 rem;
- 提供了全局样式和局部样式;
- WXSS 仅支持部分 CSS 选择器
- .class 和 #id
- element
- 并集选择器、后代选择器
- ::after 和 ::before 等伪类选择器
rpx 尺寸单位
rpx ( responsive pixel ) 是微信小程序独有的,用来解决屏幕适配的尺寸单位。
rpx 的实现原理非常简单,鉴于不同设备屏幕的大小不同,为了实现屏幕自动适配,rpx 把所有设备的屏幕,在宽度上等分为750份 ( 即:当前屏幕的总宽度为 750 rpx )
@import 样式导入
使用 WXSS 提供的 @import 语法,可以导入外联的样式表。@import 后跟需要导入外联样式表的相对路径,用 ; 表示语句结束。
@import "global.wxss";
JS
处理用户的操作,如响应用户的点击、获取用户的位置等。
小程序中的 JS 文件分为三大类:
- app.js:整个小程序项目的入口文件,通过调用 App() 函数来启动小程序;
- 页面的 .js 文件:当前页面的入口文件,通过调用 Page() 函数来创建并运行页面;
- 普通的 .js 文件:用来封装公共的函数或属性,供页面使用时调用。
页面配置
- navigationBarTitleText:导航标题文字内容
- navigationBarBackgroundColor:导航栏背景颜色,仅支持 16 进制颜色
- navigationBarTextStyle:导航标题颜色,仅支持 black / white
- backgroundColor:窗口背景色,仅支持 16 进制颜色
- backgroundTextStyle:下拉 loading 样式,仅支持 dark / light
- enablePullDownRefresh:是否全局开启下拉刷新
- onReachBottomDistance:页面上拉触底事件触发时距页面底部距离,单位 px,默认为 50
组件
组件的分类
小程序中的组件也是宿主环境提供的,开发者可以基于组件快速搭建页面结构。官方将小程序的组件分为 9 大类:
- 视图容器
- 基础内容
- 表单组件
- 导航组件
- 媒体组件
- map 地图组件
- canvas 画布组件
- 开放能力
- 无障碍访问
视图容器组件
view
普通视图区域,类似于 HTML 中的 div,是一个块级元素,用于实现页面布局
<view class="container">
<view>A</view>
</view>
scroll-view
可滚动的视图区域,用来实现滚动效果,配合 scroll-x 或 scroll-y 使用
<scroll-view class="scroll-container" scroll-y>
...
</scroll-view>
swiper / swiper-item
轮播图容器组件和项目组件
<swiper class="swiper-container">
<swiper-item>A</swiper-item>
<swiper-item>B</swiper-item>
<swiper-item>C</swiper-item>
</swiper>
基础内容组件
text
文本组件,小程序中只有 text 组件支持长按文本复制,需添加属性 selectable
<text selectable>https://puji.design</text>
rich-text
富文本组件,可通过 nodes 属性节点,把 HTML 字符串渲染为 WXML 结构
<rich-text nodes="<h1 style='color: blue'>标题</h1>"></rich-text>
表单组件
button
可通过 open-type 属性调用微信提供的各种功能(客服、转发、获取用户授权、获取用户信息等)
type,size,plain
导航组件
navigator
媒体组件
image
mode 属性
<image src="..."></image>
<image src="..." mode="widthFix"></image>
图片组件,默认宽度约 300px,高度约 240px
map 地图组件
canvas 画布组件
开放能力
无障碍访问
API
小程序中的 API 是由宿主环境提供的,通过这些丰富的小程序 API,开发者可以方便的调用微信提供的能力,如获取用户信息、本地存储、支付功能等。
API 的分类
- 事件监听 API:以on开头,用来监听事件的触发
- 同步 API:以 Sync 结尾,同步 API 的执行结果,可以通过函数返回值直接获取,如果执行出错会抛出异常
- 异步 API:需要通过 success、fail、complete接收调用的结果,类似 jQuery 中的 $.ajax(options)
数据绑定
在 data 中定义数据
在页面对应的 .js 文件中,把数据定义到 data 对象中
Page({
data: {
info: 'Hello world',
imgSrc: 'https://puji.design/logo.png',
randomNum: Math.random() * 10,
randomFloat: Math.random().toFixed(2)
}
})
在 WXML 中使用数据
把 data 中的数据绑定到页面中渲染,使用 mustache 语法 ( 双花括号 ) 将变量包起来即可
<view>{{ info }}</view>
<image src="{{ imgSrc }}"></image>
<view>{{ randomNum >= 5 ? '大于等于5' : '小于5' }}</view>
<view>{{ randomFloat * 100 }}</view>
Mustache 语法的主要应用场景:
- 绑定内容
- 绑定属性
- 运算(三元运算、算数运算等)
事件绑定
tap
手指触摸后马上离开,类似于 click
bindtap 或 bind:tap
<button bindtap="btnTapHandler">按钮</button>
input
文本框中输入事件
bindinput 或 bind:input
<input bindinput="inputHandler"></input>
change
状态改变时触发
bindchange 或 bind:change
事件对象的属性列表
- type
- timeStamp
- target
- currentTarget
- detail
- touches
- changedTouches
事件传参
可以为组件提供 data-* 自定义属性传参,其中 * 表示参数名称
<button bindtap="btnHandler" data-info="{{3}}">事件传参</button>
// info 为参数名, 3 为参数值
条件渲染
可结合 block 标签进行使用
wx:if
条件满足时则显示
<view wx:if="{{condition}}">True</view>
wx:elif
wx:else
hidden
条件满足时则隐藏
<view hidden="{{condition}}">PUJI</view>
wx:fi 和 hidden 的对比
- wx:if 以动态创建和移除元素的方式,控制元素的展示与不展示
- hidden 以切换样式的方式 ( display: none / block ) ,控制元素的显示与隐藏
- 当需要频繁切换的时候,使用 hidden 对于性能来说更好
- 控制条件比较复杂时则使用 wx:if
列表渲染
wx:for
通过 wx:for 可以根据指定的数组,循环渲染重复的组件结构
<view wx:for={{array}}">
索引:{{index}} 当前项:{{item}}
</view>
wx:for-index
指定循环项的索引的变量名
wx:for-item
指定当前项的变量名
<view wx:for"{{array}}" wx:for-index="idx" wx:for-item="itemName">
索引:{{idx}} 当前项:{{itemName}}
</view>
wx:key
类似于 Vue 列表渲染中的 :key ,小程序在实现列表渲染时,也建议为渲染出来的列表项指定唯一的 key 值,从而提高渲染的效率。注:key 值里的变量不需要花括号。
data: {
userList: [
{ id: 1, name: 'Digital' },
{ id: 2, name: 'Branding' },
{ id: 3, name: 'Coding' }
]
}
<view wx:for="{{userList}}" wx:key="id">{{item.name}}</view>
网络数据请求
出于安全性方面的考虑,小程序官方对数据接口的请求作出了如下限制:
- 只能请求 HTTPS 类型的接口
- 必须将接口的域名添加到信任列表中
wx.request()
调用微信小程序提供的 wx.request() 方法,可以发起 GET / POST 数据请求
wx.request({
url: 'https://puji.design', // 请求的接口地址
methord: 'GET', // 请求的方式
success:(res) => { // 请求成功之后的回调函数
console.log(res)
}
})
wx.request({
url: 'https://puji.design', // 请求的接口地址
methord: 'POST', // 请求的方式
data: { // 发送到服务器的数据
name: 'PUJI',
age: 36
},
success:(res) => { // 请求成功之后的回调函数
console.log(res)
}
})
页面加载时请求数据
onload: function (options) {
this.fn()
}
页面导航
页面导航指页面之间的相互跳转
页面导航的两种方式
- 声明式导航:在页面上声明一个 <navigator> 导航组件,通过点击实现页面跳转
- 编程式导航:调用小程序的导航 API 实现页面的跳转
声明式导航
跳转到 tabBar 页面
tabBar 页面指的是被配置为 tabBar 的页面,在使用 <navigator> 组件跳转到指定的 tabBar 页面时,需要指定 url 属性和 open-type 属性
- url 表示要跳转的页面地址,必须以 “/” 开头
- open-type 表示要跳转的方式,必须为 switchTab
<navigator url="/pages/user/user" open-type="switchTab">导航到个人中心页面</navigator>
跳转到其他页面
在使用 <navigator> 组件跳转到非 tabBar 页面时,需要指定 url 属性,open-type 属性可以省略。
- url 表示要跳转的页面地址,必须以 “/” 开头
- open-type 表示要跳转的方式,必须为 navigate
<navigator url="/pages/info/info" open-type="navigate">导航到普通页面</navigator>
后退导航
如果要后退到上一页或多级页面,则需要指定 open-type 属性和 delta 属性,如果只是后退到上一页,delta 可以省略。
- open-type 的值必须是 navigateBack,表示要进行后退导航
- delta 值必须是数字,表示要后退的层级
<navigator open-type="navigateBak" delta="1">返回到上一页</navigator>
编程式导航
跳转到 tabBar 页面
调用 wx.switchTab(Object object) 方法,可以跳转到 tabBar 页面。其中 Object 参数对象的属性列表如下:
- url ( 必填 ):需要跳转的 tabBar 页面的路径,路径后不能带参数
- success:调用成功的回调函数
- fail:调用失败的回调函数
- complete:调用结束的回调函数(成功/失败都会执行)
<button bindtap="gotoMessage">跳转到 Message 页面</button>
gotoMessage() {
wx.switchTab({
url: 'pages/message/message'
})
}
跳转到其他页面
调用 wx.navigateTo(Object object) 方法,可以跳转到非 tabBar 页面。其中 Object 参数对象的属性列表如下:
- url ( 必填 ):需要跳转的 tabBar 页面的路径,路径后不能带参数
- success:调用成功的回调函数
- fail:调用失败的回调函数
- complete:调用结束的回调函数(成功/失败都会执行)
<button bindtap="gotoInfo">跳转到 Info 页面</button>
gotoInfo() {
wx.navigateTo({
url: 'pages/info/info'
})
}
后退导航
调用 wx.navigateBack(Object object) 方法,可以返回上一页面或多级页面。其中 Object 参数对象的属性列表如下:
- delta:返回的页面数,如果 delta 大于现有的页面数,则返回到首页
- success:调用成功的回调函数
- fail:调用失败的回调函数
- complete:调用结束的回调函数(成功/失败都会执行)
<button bindtap="goBack">后退</button>
goBack() {
wx.navigateBack()
}
导航传参
导航参分为声明式导航传参和编程式导航传参
声明式导航传参
- 参数与路径之间使用 ? 分隔
- 参数键与参数值用 = 相连
- 不同参数用 & 分隔
<navigator url="/page/info/info?name=PUJI&age=36">下一页</navigator>
编程式导航传参
调用 wx.navigatorTo(Object object) 方法跳转页面时,也可以携带参数
<button bindtap="gotoInfo">跳转到 Info 页面</button>
gotoInfo() {
wx.navigateTo({
url: 'pages/info/info?name=PUJI&age=36'
})
}
在 onLoad 中接收导航参数
通过声明式导航传参或编程式导航传参所携带的参数,可以直接在 onLoad 事件中直接获取到
onLoad: function(options) {
console.log(options)
}
页面事件
下拉刷新
下拉刷新式移动端的专有名词,指通过手指在屏幕上的下拉滑动操作,从而重新加载页面数据的行为。
监听页面下拉刷新事件
在页面的 .js 文件中,通过 onPullDownRefresh() 函数,即可监听当前页面的下拉刷新事件。
onPullDownRefresh: function () {
...
}
停止下拉刷新效果
当处理完成下拉刷新后,下拉刷新的 loading 效果会一直显示,不会自动消失,所以需要手动隐藏 loading 效果。调用 wx.stopPullDownRefresh() 可以停止当前页面的下拉刷新。
onPullDownRefresh: function () {
...
wx.stopPullDownRefresh()
}
上拉触底
通过手指在屏幕上的上拉滑动操作,从而实现加载更多数据的行为
监听页面上拉触底事件
在页面的 .js 文件中,通过 onReachBottom() 函数,即可监听当前页面的上拉触底事件。
onReachBottom: function () {
...
}
上拉触底截流
- 在 data 中定义 isLoading 节流阀
- 在执行函数中修改 isLoading 节流阀的值
- 在 onReachBottom 中判断节流阀的值
onReachBottom: function () {
...
}
生命周期
生命周期 ( Life Cycle ) 是指一个对象从创建 -> 运行 -> 销毁的整个阶段,强调的是一个时间段。
小程序中生命周期分为两类:
- 应用生命周期:特指小程序从启动 -> 运行 -> 销毁的过程
- 页面生命周期:特指每个页面的加载 -> 渲染 -> 销毁的过程
生命周期函数
由小程序框架提供的内置函数,会伴随着生命周期,自动按次序执行。生命周期函数的作用是允许程序员在特定的时间点,执行某些特定的操作。如页面刚加载的时候,可以在 onLoad 生命周期函数中初始化页面的数据。
生命周期强调的是时间段,生命周期函数强调的是时间点。
生命周期函数的分类
- 应用的生命周期函数:特指小程序从启动 -> 运行 -> 销毁期间依次调用的那些函数
- 页面的生命周期函数:特指小程序中,每个页面从加载 -> 渲染 -> 销毁期间依次调用的那些函数
应用生命周期函数
小程序的应用生命周期函数需要在 app.js 中进行声明
App({
// 小程序初始化完成时,执行此函数,全局只触发一次,可以做一些初始化的工作
onLaunch: function(options) {},
// 小程序启动,或从后台进入前台显示时触发
onShow: function(options) {},
// 小程序从前台进入后台时触发
onHide: function() {}
})
页面生命周期函数
小程序的应用生命周期函数需要在响应页面的 .js 中进行声明
Page({
// 监听页面加载,一个页面只调用一次
onLoad: function(options) {},
// 监听页面显示
onShow: function() {},
// 监听页面初次渲染完成,一个页面只调用1次
onReady: function() {},
// 监听页面隐藏
onHide: function() {},
// 监听页面卸载,一个页面只调用1次
onUnload: function() {},
})
WXS 脚本
WXS ( WeiXin Script ) 是小程序独有的一套脚本语言,结合 WXML,可以构建出页面的结构。
WXML 中无法调用在页面的 .js 中定义的函数,但是 WXML 中可以调用 WXS 中定义的函数。因此,小程序中 WXS 的典型应用场景就是“过滤器”。
WXS 的特点
- 与 JavaScript 不同:WXS 语言的设计大量借鉴的 JavaScript的语法,但是本质上 WXS 和 JavaScript 是完全不同的两种语言
- 不能作为组件的事件回调:WXS 典型的应用场景是“过滤器”,常配合 Mustache 语法进行使用
- 隔离型:WXS 的运行环境和其他 JavaScript 代码是隔离的
- WXS 不能调用 JS 中定义的函数
- WXS 不能调用小程序提供的 API
- 性能好:在 ios 设备上小程序比 WXS 比 JavaScript 代码快 2 ~ 20 倍,但是在 android 设备上运行效率无差异
WXS 和 JavaScript 的关系
- WXS 有自己的数据类型:
- Number 数值型
- String 字符串型
- Boolean 布尔型
- Object 对象
- Function 函数
- Array 数组
- Data 日期
- Regexp 正则
- WXS 不支持类似于 ES6 及以上的语法形式:
- 不支持 let、const、解构赋值、展开运算符、箭头函数、对象属性简写等
- 支持 var 定义变量,普通 function 函数等类似于 ES5 的语法
- WXS 遵循 CommonJS 规范:
- module 对象
- require() 函数
- module.exports 对象
内嵌 WXS 脚本
WXS 代码可以编写在 WXML 文件中的 <wxs> 标签内,就像 JavaScript 代码可以编写在 HTML 文件中的 <script>标签内一样。
WXML 文件中的每一个 <wxs></wxs> 标签内,必须提供 module 属性,用来指定当前 WXS 的模板名称,方便在 WXML 中访问模块中的成员。
<view>{{m1.toUpper(username)}}</view>
<wxs module="m1">
module.exports.toUpper = function(str) {
return str.toUpperCase()
}
</wxs>
定义外联的 WXS 脚本
WXS 代码还可以编写在以 .wxs 为后缀的文件内,就像 JavaScript 代码可以编写在以 .js 为后缀名的文件中
function toLower(str) {
return str.toLowerCase()
}
module.export = {
toLower: toLower
}
使用外联的 WXS 脚本
在 WXML 中引入外联的 WXS 脚本时,必须为 <wxs> 标签添加 module 和 src 属性
- module 用来指定模版的名称
- src用来指定要引入的脚本的路径,且必须是相对路径
<view>{{m2.toLower(country)}}</view>
<wxs src="../../utils/tools.wxs" module="m1"></wxs>
其他
this.setData()
给页面data中的数据重新赋值
this.setData(dataObject)
// 示例
Page({
data: {
count: 0
},
changeCount() {
this.setData({
count:this.data.count + 1
})
}
})
showLoading() / hideLoading()
getDatas() {
wx.showLoading({
title: '加载中...'
})
wx.request({
...
complete: () {
wx.hideLoading()
}
})
}
小程序版本
开发版本
使用开发者工具,可将代码上传到开发版本中,开发版本只保留每个人最新的一份上传的代码。点击提交审核,可将代码提交审核。开发版本可删除,不影响线上版本和审核中版本的代码。
体验版本
可以选择某个开发版本作为体验版本,并且选取一份体验版本。
审核中的版本
只有一份代码处于审核中。有审核结果后可发布到线上,也可直接重新提交审核,覆盖原审核版本
线上版本
线上所有用户使用的版本,该版本代码在新版本代码发布后会被覆盖
发布上线
- 上传代码
- 提交审核
- 发布上线
实战案例
基础案例
https://www.bilibili.com/video/BV1834y1676P?p=36
上拉触底
https://www.bilibili.com/video/BV1834y1676P?p=44
加载数据
https://www.bilibili.com/video/BV1834y1676P?p=52
参考链接
Bilibili 视频教程
https://www.bilibili.com/video/BV1834y1676P