上个月写了一个公司的微信小程序项目,趁热打铁,分享一篇开发教程,希望对还没有小程序开发经验的同学有点帮助,对于有 VUE 经验的同学来说,看完这一篇就可以直接上手。
这篇文章我们用提问的方式来完成,带着问题来学习更轻松哟!
搜索 tips 可以直接查看避坑经验。
小程序的框架原理?
视图层加逻辑层,视图层负责渲染,逻辑层负责处理事件。渲染层和逻辑层处于两个线程,通过 微信客户端 通讯。
小程序开发框架的目标是通过尽可能简单、高效的方式让开发者可以在微信中开发具有原生 APP 体验的服务。整个小程序框架系统分为两部分:
逻辑层(App Service)和 视图层(View)。
小程序提供了自己的视图层描述语言 WXML 和 WXSS,以及基于 JavaScript 的逻辑层框架,并在 视图层与逻辑层间提供了数据传输和事件系统,让开发者能够专注于数据与逻辑。
为什么微信小程序中不能使用 alert?
因为小程序中没有 window 和 document 对象
小程序框架的逻辑层并非运行在浏览器中,因此 JavaScript 在 web 中一些能力都无法使用,如 window,document 等。
为什么小程序中不能使用 div?
因为小程序的 WXML 并不是原生的 HTML,而是微信自己实现的基于 XML 的语法。在开发过程中使用微信小程序的标签语言规范。 举个例子:
- view 标签代替 div
- image 标签代替 img
小程序 js 运行环境和浏览器 js 运行环境有什么不同?
小程序中开发者工具的 js 运行在 nw.js 中,浏览器中的 js 运行在浏览器的 V8 引擎中。
微信小程序运行在多种平台上:iOS/iPadOS 微信客户端、Android 微信客户端、Windows PC 微信客户端、Mac 微信客户端、小程序硬件框架和用于调试的微信开发者工具等。不同运行环境下,脚本执行环境以及用于组件渲染的环境是不同的,性能表现也存在差异:
在 iOS、iPadOS 和 Mac OS 上,小程序逻辑层的 JavaScript 代码运行在 JavaScriptCore 中,视图层是由 WKWebView 来渲染的,环境有 iOS 14、iPad OS 14、Mac OS 11.4 等;
在 Android 上,小程序逻辑层的 JavaScript 代码运行在 V8 中,视图层是由基于 Mobile Chromium 内核的微信自研 XWeb 引擎来渲染的;
在 Windows 上,小程序逻辑层 JavaScript 和视图层都是用 Chromium 内核;
在 开发工具上,小程序逻辑层的 JavaScript 代码是运行在 NW.js 中,视图层是由 Chromium Webview 来渲染的。
运行环境 | 逻辑层 | 渲染层 |
---|---|---|
iOS | JavaScriptCore | WKWebView |
安卓 | V8 | chromium 定制内核 |
小程序开发者工具 | NWJS | Chrome WebView |
小程序开发的前置工作?
- 使用一个还未注册过公众号或者小程序的邮箱注册一个小程序账号
- 添加开发者:小程序管理后台-管理-成员管理-项目成员
- 开发者下载最新版的微信开发者工具,选择一个模板(支持 typescript)填入 APPID 生成项目
- 熟悉微信开发者工具界面功能
tips:微信开发者工具界面的内容比较多,可以将模拟器界面分离出来,在两个界面展示
小程序的相关文件类型?
类型 | 描述 |
---|---|
.WXML | 标签语言,结合基础组件、事件系统,可以构建出页面的结构 |
.WXSS | 样式语言,用于描述 WXML 的组件样式 |
.json | 页面配置,例如:导航栏标题、是否支持下拉刷新等 |
.js | js 逻辑,事件交互逻辑、http 请求等 |
tips:iOS 设备对于 input 标签的 maxlength 属性支持不流畅,当输入法为中文时,会将拼音也计算为 value 长度,替代方案为在 bindinput 方法中监听长度变化
如何新增一个页面?
在小程序开发者工具上,找到项目的根目录下的app.json,配置page字段
{
"pages":[
"pages/test/index",
]
}
保存之后会自动在pages目录下生成一个test文件夹,文件夹内包含一个页面需要的四个文件。
tips:
- 只有在微信开发者工具上才能触发自动创建文件,在VScode中不能触发
- 如果使用VScode开发小程序,需要安装 "小程序开发助手" 插件
如何设置底部 tab 栏?
在 app.json 中配置 tabBar 字段
"tabBar": {
"color": "#bfbfbf",
"selectedColor": "#2056F0",
"list": [
{
"pagePath": "pages/home/index",
"text": "首 页",
"iconPath": "/images/home.png",
"selectedIconPath": "/images/home2.png"
},
{
"pagePath": "pages/customer/index",
"text": "客 户",
"iconPath": "/images/customer.png",
"selectedIconPath": "/images/customer2.png"
},
{
"pagePath": "pages/setting/index",
"text": "设 置",
"iconPath": "/images/mine.png",
"selectedIconPath": "/images/mine2.png"
}
]
}
其他页面配置也可在 app.json 中配置 页面配置
如何设置统一背景色?
在 app.wxss 中设置:
page {
background-color: #f5f7fa;
}
css 单位
rpx(responsive pixel): 可以根据屏幕宽度进行自适应。规定屏幕宽为 750rpx。如在 iPhone6 上,屏幕宽度为 375px,共有 750 个物理像素,则 750rpx = 375px = 750 物理像素,1rpx = 0.5px = 1 物理像素。
tips:ios 设备上不支持 gap 属性
小程序的生命周期函数?
函数 | 描述 |
---|---|
onLoad | 页面加载完毕时执行,初始化数据放在这里 |
onReady | 页面初次渲染完成时执行 |
onShow | 页面显示时执行,再次进入页面时触发的逻辑放在这里 |
onHide | 页面隐藏时执行 |
小程序的双向绑定和 vue 有什么不同?
vue 中的双向绑定数据变动时自动触发视图更新,在小程序中需要调用 this.setData 方法出发视图更新
小程序中的消息提示框
wx.showToast({
title: "请求成功",
icon: "success",
duration: 1500,
});
tips: 在实际使用的过程中,会发现这个消息提示框不能按照设置的持续时间执行,我们可以手动 hide 消息提示框:
setTimeout(function () {
wx.hideToast();
wx.navigateBack({
delta: 1,
});
}, 1000);
小程序中的模态对话框
wx.showModal({
title: "提示",
content: "这是一个模态弹窗",
success(res) {
if (res.confirm) {
console.log("用户点击确定");
} else if (res.cancel) {
console.log("用户点击取消");
}
},
});
小程序如何更新页面?
调用 setData 方法实现局部数据刷新
页面间传递数据的方式?
- 在页面跳转的 URL 后面添加参数,实现页面间传参
// a页面
wx.navigateTo({
url: '../customerDetail/index?customerId='+ id,
success: function(res) {}
})
// b页面
onLoad: function (options) {
const customerId = options.customerId
}
- 借助 app.globalData,实现一处更改全局更新
// a页面
app.globalData.userInfo = { name: "testName", age: 18 };
// b页面
const app = getApp();
const name = app.globalData.userInfo.name;
- 使用 storage
如何实现数据绑定?
// WXML
<view> {{ message }} </view>;
// js
Page({
data: {
message: "Hello MINA!",
},
});
如何实现事件绑定?
bindtap、catchtap 等
事件分为冒泡事件和非冒泡事件:
冒泡事件:当一个组件上的事件被触发后,该事件会向父节点传递。
非冒泡事件:当一个组件上的事件被触发后,该事件不会向父节点传递。
// WXML
<view bindtap="viewTap"> click me </view>;
// js
Page({
viewTap: function () {
console.log("view tap");
},
});
如何向事件中传递参数?
事件对象可以携带额外信息,如 id, dataset, touches。
// WXML
<view wx:for="list" data-name="{{item.name}}" bindtap="ontap"></view>
// js
ontap:function(e){
const itemName = e.currentTarget.dataset.name
}
bindtap 和 catchtap 的区别?
- bindtap 绑定事件,允许事件冒泡
- catchtap 绑定事件,并阻止事件冒泡
当子节点和父节点都有点击事件时,子节点使用 catchtap,父节点使用 bindtap
页面跳转的方式有哪些?
路由方法 | 描述 |
---|---|
wx.navigateTo | 保留当前页面,跳转到应用内的某个页面。但是不能跳到 tabbar 页面。最多 10 层页面栈 |
wx.redirectTo | 关闭当前页面,跳转到应用内的某个页面。但是不允许跳转到 tabbar 页面 |
wx.switchTab | 跳转到 tabBar 页面,并关闭其他所有非 tabBar 页面 |
wx.navigateBack | 关闭当前页面,返回上一页面或多级页面 |
wx.reLaunch | 关闭所有页面,打开到应用内的某个页面 |
条件渲染怎么做?
<view wx:if="{{condition}}">按条件展示</view>
tips:频繁渲染用 hidden 代替,类似于 VUE 中 v-if 和 v-show 的区别 条件渲染
循环渲染怎么做?
<view wx:for="{{list}}" wx:key="id" wx:for-item="user">
{{user.name}}
</view>
如何请求数据?
在小程序管理后台-开发-开发管理-开发设置-服务器域名-request 合法域名 中配置服务端域名
wx.request({
url: "https://www.test.com/api/userList",
header: {},
data: {
pageIndex: 1,
pageSize: 10,
},
timeout: 20000,
success: function (res) {
// 成功回调
},
fail: function (e) {
// 失败回调
},
});
tips:
- GET 请求传递数组会被编码,所以传递数组参数时需要使用使用 post 请求
- header 中的字段值不支持中文 必须编码后传输,可以使用 encodeURIComponent 方法
- 支持 promise 封装
上传图片怎么做?
- 在小程序管理后台-开发-开发管理-开发设置-服务器域名-uploadFile 合法域名中配置服务器域名
- 使用 wx.uploadFile,一般配合 wx.chooseImage 等方法使用:
wx.uploadFile({
url: "url",
filePath: "filePaths",
name: "file",
formData: {
user: "test",
},
success: function (res) {},
fail: function (e) {},
complete: function (res) {},
});
tips: 注意后端支持的最大图片 size,不同手机拍照的图片大小差异很大,andriod 大概 6M,IOS 大概 10M
播放录音怎么做?
const audioContext = wx.createInnerAudioContext({
useWebAudioImplement: true,
});
audioContext.src = "audioUrl";
audioContext.play(); // 播放
如何实现下拉刷新?
在 json 文件中设置允许下拉刷新:
"enablePullDownRefresh": true,
在 js 文件中添加下拉刷新的回调:
onPullDownRefresh: function () {
// 下拉回调
// ...
// 回调完成之后停止下拉刷新
wx.stopPullDownRefresh();
},
一般用于下拉刷新页面请求。
如何实现触底更新?
在 js 页面中添加 onReachBottom 的回调:
onReachBottom: function () {
// 触底回调
}
一般用于列表数据太多时,分页加载。
如何引入 moment 等 npm 包?
- 在小程序的根目录下执行:
npm i moment -S
- 在微信开发者工具界面找到-工具-构建 npm
如何使用开发者工具开发企业微信小程序?
- 微信开发者工具-工具-插件-添加企业微信小程序插件
- 选择当前使用的企业
tips:
- 开发人员从企业微信中打开小程序看到的总是开发版
- 给测试人员添加体验版权限而不是开发者,原因同上
- 企业微信获取到的通讯录个人信息中不包含员工的姓名和手机号,只有 id 和别名等信息
小程序何时销毁?
如果用户很久没有使用小程序,或者系统资源紧张,小程序会被「销毁」,即完全终止运行。具体而言包括以下几种情形:
当小程序进入后台并被「挂起」后,如果很长时间(目前是 30 分钟)都未再次进入前台,小程序会被销毁。
当小程序占用系统资源过高,可能会被系统销毁或被微信客户端主动回收。
在 iOS 上,当微信客户端在一定时间间隔内连续收到系统内存告警时,会根据一定的策略,主动销毁小程序,并提示用户 「运行内存不足,请重新打开该小程序」。具体策略会持续进行调整优化。
建议小程序在必要时使用 wx.onMemoryWarning 监听内存告警事件,进行必要的内存清理。
基础库 1.1.0 及以上,1.4.0 以下版本: 当用户从扫一扫、转发等入口(场景值为 1007, 1008, 1011, 1025)进入小程序,且没有置顶小程序的情况下退出,小程序会被销毁。
tips: 小程序打开后,在短期内再次进入小程序不会从头开始执行,而会直接吊起内存中的页面到前台运行。
tips: 借助 wx.getUpdateManager 实现版本更新
小程序的环境控制?
-
开发版 扫描开发者工具上的预览二维码生成开发版
在小程序管理后台的-管理-成员管理-项目成员中添加开发者
在小程序管理后台的-管理-版本管理-开发版本中查看体验版二维码 -
体验版
在开发者工具上点击上传后的代码生成体验版
在小程序管理后台的-管理-成员管理-项目成员中添加体验成员 -
审核版
在小程序管理后台的-管理-版本管理-审核版本中查看审核详情 -
正式版
在小程序管理后台的-管理-版本管理-线上版本中查看线上版本详情tips:
- 设置体验版时,需要注意设置页面路径,可以只提供体验单个页面
- 提交审核时,同时提交图片和操作视频,更容易通过审核
- 提交审核的版本,必须满足没有任何权限也能正常进入页面(可提供游客身份),否则无法审核通过
- 生成的开发版预览码 30 分钟内过期,体验码长期有效
小程序的发布流程?
在微信开发者工具中点击上传代码
在小程序管理后台的-管理-版本管理-开发版本中查看当前版本并提交审核
在小程序管理后台的-管理-版本管理-审核版本中查看审核详情
tips: 小程序发布支持灰度发布,可以指定微信号发布,非常 nice!
写在最后
如果是新的微信小程序项目,建议直接使用微信小程序原生方式开发,看了很多吐槽原生不好用的文章,发现截止 2022 年的现在,微信官方已经修复和优化了大部分的功能,特别是非常重要的功能,原生开发已经没有太大的阻碍。 关注小姐姐,一起学一学!