微信小程序作为一种不需要下载安装即可使用的应用,它实现了应用“触手可及”的梦想,用户扫一扫或者搜一下即可打开应用。对于开发者而言,小程序是一种全新的开放能力,它基于微信提供的框架和API,让开发者能够快速构建出高质量的本地应用。本指南将从基础入门讲起,逐步深入到高级实战技巧,并提供常见问题的解决方案,帮助你从入门走向精通。
一、入门基础:环境搭建与项目结构
在开始编写代码之前,我们需要搭建好开发环境并了解小程序的基本构成。
1.1 开发工具的安装与使用
微信官方提供了“微信开发者工具”,它是小程序开发的主要IDE。你可以访问微信公众平台下载对应操作系统的版本。
安装步骤:
- 下载安装包并安装。
- 打开开发者工具,使用微信扫码登录。
- 选择“小程序”项目,填写项目目录和AppID(在公众平台账号后台可获取,若仅为学习,可选择“不使用云服务”并创建测试号)。
1.2 小程序项目结构
一个标准的小程序项目主要包含以下几种类型的文件,它们必须存放在指定的目录下:
.json配置文件:全局配置(app.json)和页面配置(page.json)。.wxml模板文件:类似于HTML,用于描述页面的结构。.wxss样式文件:类似于CSS,用于描述页面的样式。.js逻辑文件:用于处理页面的交互逻辑、数据绑定和网络请求。
示例项目结构:
miniprogram/
├── app.js // 小程序入口文件
├── app.json // 全局配置
├── app.wxss // 全局样式
├── pages/ // 页面目录
│ ├── index/ // 首页
│ │ ├── index.js // 首页逻辑
│ │ ├── index.json // 首页配置
│ │ ├── index.wxml // 首页结构
│ │ └── index.wxss // 首页样式
│ └── logs/ // 日志页
│ ├── logs.js
│ ├── logs.json
│ ├── logs.wxml
│ └── logs.wxss
└── utils/ // 工具类
└── util.js
1.3 全局配置 app.json
app.json 是小程序的全局配置文件,决定了小程序的所有页面路径、界面表现、网络超时时间等。
常用配置项:
pages: 定义所有页面路径,数组的第一项是小程序的初始页面。window: 定义小程序所有页面的顶部表现,如导航栏背景色、标题文字等。tabBar: 如果小程序是一个多 tab 应用,可以通过该配置指定 tab栏的表现。
代码示例:
{
"pages": [
"pages/index/index",
"pages/logs/logs"
],
"window": {
"navigationBarTitleText": "我的小程序",
"navigationBarBackgroundColor": "#007AFF",
"navigationBarTextStyle": "white"
},
"tabBar": {
"list": [
{
"pagePath": "pages/index/index",
"text": "首页",
"iconPath": "images/home.png",
"selectedIconPath": "images/home-selected.png"
},
{
"pagePath": "pages/logs/logs",
"text": "日志",
"iconPath": "images/log.png",
"selectedIconPath": "images/log-selected.png"
}
]
}
}
二、核心开发技术:WXML 与 WXSS
小程序的视图层由 WXML 和 WXSS 组成,它们分别负责结构的搭建和样式的定义。
2.1 WXML 数据绑定与列表渲染
WXML 支持数据绑定、列表渲染、条件渲染等,语法使用双大括号 {{ }}。
数据绑定:
在 .js 文件中定义 data 对象,在 .wxml 中通过 {{ variable }} 引用。
JS代码 (index.js):
Page({
data: {
message: 'Hello, Mini Program!',
userInfo: {
name: '张三',
age: 25
}
}
})
WXML代码 (index.wxml):
<view>{{ message }}</view>
<view>姓名: {{ userInfo.name }}, 年龄: {{ userInfo.age }}</view>
列表渲染 (wx:for): 用于循环渲染一个数组,生成多个相同的组件结构。
JS代码 (index.js):
Page({
data: {
items: [
{ id: 1, name: '苹果' },
{ id: 2, name: '香蕉' },
{ id: 3, name: '橙子' }
]
}
})
WXML代码 (index.wxml):
<view wx:for="{{items}}" wx:key="id">
{{index}}: {{item.name}}
</view>
注意:
wx:key是为了提高列表渲染的性能,保持节点的唯一性。
2.2 WXSS 样式与尺寸单位
WXSS 在 CSS 的基础上扩展了两个特性:尺寸单位和样式导入。
尺寸单位 rpx (responsive pixel): rpx 是微信小程序的响应式像素单位,它规定了屏幕宽为 750rpx。无论屏幕宽度是多少,1rpx 的长度都会自动换算。 例如,在 iPhone 6 上,屏幕宽度为 375px,共 750rpx,因此 1rpx = 0.5px。
代码示例:
/* index.wxss */
.container {
width: 750rpx; /* 在任何屏幕上都占满宽度 */
height: 200rpx;
background-color: #f0f0f0;
}
.box {
/* 使用 flex 布局 */
display: flex;
justify-content: center;
align-items: center;
width: 50%; /* 百分比相对于父容器 */
height: 100rpx;
margin: 10rpx auto;
}
三、逻辑层与数据驱动:JavaScript
小程序的逻辑层主要由 JavaScript 组成,核心是 Page 和 Component 构造器。
3.1 Page 页面生命周期与事件处理
Page 构造器用于定义页面的数据、生命周期函数和事件处理函数。
生命周期函数:
onLoad(options): 页面加载时触发,适合获取初始化数据。onShow(): 页面显示时触发。onReady(): 页面初次渲染完成时触发。onHide(): 页面隐藏时触发。onUnload(): 页面卸载时触发。
事件绑定与处理:
在 WXML 中使用 bindtap 绑定点击事件,在 JS 中定义对应的处理函数。
WXML代码:
<button bindtap="handleClick" data-id="123">点击我</button>
JS代码:
Page({
// 定义数据
data: {
count: 0
},
// 点击事件处理函数
handleClick: function(e) {
// 获取 data 中的数据
const currentCount = this.data.count;
// 更新数据 (必须使用 this.setData)
this.setData({
count: currentCount + 1
});
// 获取 WXML 传递的参数
const id = e.currentTarget.dataset.id;
console.log('按钮ID:', id);
}
})
3.2 模块化开发
为了代码复用,我们可以将公共的逻辑抽离到 utils 目录下,通过 module.exports 导出,在其他页面通过 require 引入。
utils/util.js:
const formatTime = (date) => {
const year = date.getFullYear()
const month = date.getMonth() + 1
const day = date.getDate()
return `${year}/${month}/${day}`
}
module.exports = {
formatTime: formatTime
}
pages/index/index.js:
const util = require('../../utils/util.js')
Page({
onLoad: function() {
const now = new Date()
console.log(util.formatTime(now)) // 输出: 2023/10/27
}
})
四、进阶实战:网络请求与 API 调用
小程序提供了丰富的 API 来访问原生能力,如网络请求、本地存储、地理位置等。
4.1 网络请求 (wx.request)
这是最常用的功能,用于与服务器交互。
代码示例:
Page({
// 发起请求的方法
fetchData: function() {
wx.request({
url: 'https://api.example.com/data', // 替换为实际接口地址
method: 'GET',
data: {
id: 1
},
header: {
'content-type': 'application/json' // 默认值
},
success: (res) => {
console.log('请求成功:', res.data);
this.setData({
serverData: res.data
});
},
fail: (err) => {
console.error('请求失败:', err);
wx.showToast({
title: '网络错误',
icon: 'none'
});
},
complete: () => {
// 无论成功失败都会执行
console.log('请求完成');
}
});
}
})
注意:
wx.request的回调函数中,success回调参数res包含statusCode,开发者需要自行判断statusCode是否为 200。
4.2 本地数据存储 (wx.setStorageSync)
用于存储用户的偏好设置或临时数据。
代码示例:
// 存储数据
wx.setStorageSync('user_key', { name: 'Alice', token: 'xyz' })
// 读取数据
const data = wx.getStorageSync('user_key')
if (data) {
console.log('读取到的用户:', data.name)
}
// 删除数据
wx.removeStorageSync('user_key')
// 清空所有数据(慎用)
// wx.clearStorageSync()
五、常见问题解决方案 (Troubleshooting)
在开发过程中,开发者经常会遇到一些棘手的问题。以下是一些高频问题的排查与解决方案。
5.1 网络请求失败 (Request:fail)
问题描述:调用 wx.request 时控制台报错 Request:fail,或者提示 url invalid。
原因分析:
- 域名问题:小程序正式版只支持
https协议,且域名必须在微信公众平台的“开发设置”-“服务器域名”中配置。 - 本地调试:如果是本地开发,未开启“不校验合法域名”。
解决方案:
- 开发阶段:在开发者工具右上角点击“详情” -> “本地设置” -> 勾选“不校验合法域名、web-view(业务域名)、TLS版本以及HTTPS证书”。
- 上线阶段:确保你的服务器支持 HTTPS,并在公众平台配置好域名。
5.2 数据更新视图不渲染 (this.setData)
问题描述:修改了 data 中的变量,但页面没有变化。
原因分析:
直接赋值 this.data.count = 10 只是修改了 JS 对象中的值,并没有触发视图层的更新。
错误写法:
this.data.count = 10; // 无效
正确写法:
this.setData({
count: 10
});
5.3 样式不生效或错乱
原因分析:
- WXSS 优先级:小程序组件有默认样式,可能被覆盖。
- 单位使用错误:使用了
px导致在不同屏幕尺寸下显示不一致。 - 类名拼写错误:WXML 中的 class 与 WXSS 中的选择器不匹配。
解决方案:
- 尽量使用
rpx作为单位。 - 使用开发者工具的“Wxml”面板检查元素绑定的 class 是否正确。
- 检查 WXSS 是否被全局样式覆盖,可以使用更具体的选择器或
!important(不推荐滥用)。
5.4 页面跳转参数传递失败
问题描述:使用 wx.navigateTo 跳转时,目标页面的 onLoad 接收不到参数。
原因分析:
URL 长度有限制,且参数必须进行 encodeURIComponent 编码(如果包含特殊字符)。
代码示例: 跳转页 (index.js):
const id = 100;
const name = "测试名称";
// 必须使用 encodeURIComponent 对参数值进行编码
const url = `/pages/detail/detail?id=${id}&name=${encodeURIComponent(name)}`;
wx.navigateTo({ url: url });
目标页 (detail.js):
Page({
onLoad: function(options) {
// options.id = "100"
// options.name = "测试名称" (自动解码)
console.log(options);
}
})
5.5 小程序审核被拒:涉及用户隐私
问题描述:小程序提交审核时,因为获取用户手机号、头像等信息被拒。
原因分析:
微信对用户隐私保护越来越严格,不再允许开发者直接通过 wx.getUserInfo 获取用户敏感信息。
解决方案:
- 使用
<button>组件的开放能力(如open-type="getPhoneNumber"获取手机号,open-type="getUserInfo"获取用户信息)。 - 配合
bindgetuserinfo或bindgetphonenumber事件回调获取加密数据,然后传给后端解密。
代码示例 (获取用户信息):
<button open-type="getUserInfo" bindgetuserinfo="handleGetUserInfo">获取用户信息</button>
Page({
handleGetUserInfo: function(e) {
console.log(e.detail); // 包含加密的用户信息
// 将 e.detail 传给后端解密
}
})
六、总结
微信小程序开发虽然入门门槛相对较低,但要精通并开发出高质量的应用,需要深入理解其数据驱动的视图层、生命周期管理以及网络通信机制。通过本指南的学习,你应该已经掌握了从环境搭建到复杂交互实现的全过程。在实际开发中,多查阅官方文档,善用开发者工具的调试功能,是解决问题的最佳途径。
