微信小程序开发实用技巧汇总
页面生命周期
| 钩子函数 | 类型 | 说明 | 触发时机 |
|---|---|---|---|
| onLoad | function | 页面加载完成时触发 | 首次进入页面调用一次,可获取页面参数 |
| onReady | function | 页面首次渲染完毕 | 仅调用一次,此时可与视图层交互 |
| onShow | function | 页面显示时触发 | 每次从后台返回或打开页面都会调用 |
| onHide | function | 页面隐藏时触发 | 进入后台或切换到其他页面时触发 |
| onUnload | function | 页面卸载时触发 | 返回上一页或页面被替换时触发 |
执行顺序:onLoad → onShow → onReady
交互事件钩子
| 钩子函数 | 类型 | 说明 |
|---|---|---|
| onPullDownRefresh | function | 监听用户下拉刷新操作 |
| onReachBottom | function | 监听页面上拉触底事件 |
| onShareAppMessage | function | 监听用户点击右上角分享 |
页面跳转方式
官方文档:wx.navigateBack
// 重新加载应用内的任意页面
wx.reLaunch({
url: '/pages/home/home'
});
// 关闭当前页面,跳转到指定页面(不支持跳转到 tabbar)
wx.redirectTo({
url: '/pages/profile/profile'
});
// 保留当前页面,跳转到指定页面(页面栈最多十层)
wx.navigateTo({
url: '/pages/detail/detail?id=1'
});
// 返回上一页面或多级页面
wx.navigateBack({
delta: 1
});
// 可通过 getCurrentPages() 获取当前页面栈信息
跨页面数据传递
方式一:URL 参数传递
// 编程式跳转携带参数
wx.navigateTo({
url: '/pages/book/detail?bookId=' + bookId + '&category=' + category
});
// 声明式跳转携带参数
<navigator url="/pages/chapter/list?bookId={{ bookId }}">章节列表</navigator>
// 接收参数
onLoad: function(query) {
console.log('书籍ID:' + query.bookId);
console.log('分类:' + query.category);
}
方式二:本地存储
| 操作 | 异步方法 | 同步方法 |
|---|---|---|
| 写入 | wx.setStorage | wx.setStorageSync |
| 读取 | wx.getStorage | wx.getStorageSync |
| 删除 | wx.removeStorage | wx.removeStorageSync |
| 清空 | wx.clearStorage | wx.clearStorageSync |
| 获取信息 | wx.getStorageInfo | wx.getStorageInfoSync |
// 写入本地存储
wx.setStorage({ key: 'userToken', data: 'abc123' });
// 读取本地存储
const token = wx.getStorageSync('userToken');
方式三:全局数据对象
// app.js 定义全局数据
App({
globalData: {
userInfo: null,
apiBase: 'https://api.example.com'
}
});
// 页面中获取全局数据
const app = getApp();
const baseUrl = app.globalData.apiBase;
列表渲染中的事件传参
<!-- wxml 文件 -->
<!-- 使用 data- 前缀定义自定义属性 -->
<view class="item-list">
<view wx:for="{{ bookList }}" wx:key="index"
data-book-id="{{ item.bookId }}"
data-position="{{ index }}"
bindtap="handleTap">
<image src="{{ item.cover }}" mode="aspectFill"></image>
<text>{{ item.name }}</text>
</view>
</view>
// js 文件
handleTap: function(event) {
const bookId = event.currentTarget.dataset.bookId;
const position = event.currentTarget.dataset.position;
this.navigateToDetail(bookId, position);
}
表单提交与 formId 获取
获取 formId
// 在 form 组件上添加 report-submit 属性
<form bindsubmit="handleSubmit" report-submit='true'>
<button form-type="submit">提交</button>
</form>
// 注意:开发工具中 formId 为模拟值,提示 "the formId is a mock one"
// 真是 formId 只能在真机上获取并提交到服务器
表单数据绑定
// wxml
<form bindsubmit="submitForm" report-submit='true'>
<input name="username" value="{{ formData.username }}"
bindinput="handleInput" placeholder="请输入用户名" />
<button form-type="submit">提交表单</button>
</form>
// js
handleInput: function(e) {
this.setData({
'formData.username': e.detail.value
});
},
submitForm: function(e) {
console.log('表单数据:', e.detail.value);
console.log('formId:', e.detail.formId);
}
WXS 过滤器使用
WXS 是小程序独有的脚本语言,可在页面中直接使用,无需引入外部 JS 文件。
// 在需要的页面引入 WXS 模块
<wxs module="utils" src="../../utils/string.wxs"></wxs>
// 使用过滤器
{{ utils.formatDate(timestamp) }}
{{ utils.ellipsis(content, 20) }}
// utils/string.wxs 文件内容
var formatDate = function(timestamp) {
var date = getDate(timestamp);
var year = date.getFullYear();
var month = date.getMonth() + 1;
var day = date.getDate();
return year + '-' + month + '-' + day;
};
var ellipsis = function(str, length) {
if (str.length <= length) return str;
return str.substring(0, length) + '...';
};
module.exports = {
formatDate: formatDate,
ellipsis: ellipsis
};
常见问题与解决方案
问题一:数据渲染延迟导致元素闪烁
现象:页面加载时,已隐藏的元素会短暂显示后再消失。
解决方案:使用 hidden 属性控制元素显示隐藏。
<view hidden="{{ isShow }}">内容区域</view>
问题二:页面栈溢出导致无法跳转
现象:小程序页面栈限制为十层,继续跳转会失败。
解决方案:
- 优先使用 wx.redirectTo 或 wx.reLaunch 替换 wx.navigateTo
- 在跳转前检查并清理重复页面
// 跳转前清理页面栈
const pages = getCurrentPages();
const samePage = pages.find(p => p.route === 'pages/index/index');
if (samePage) {
// 找到重复页面,可以选择重定向到该页面
}
问题三:页面背景色不一致
现象:页面内容不足一屏时,底部背景色与其他区域不一致。
解决方案:
/* wxss - 简单情况 */
page {
background-color: #f5f5f5;
}
/* wxss - 切换背景色时 */
.fixed-bottom {
position: fixed;
width: 100%;
height: 200rpx;
bottom: 0;
left: 0;
z-index: 1;
}
// wxml
<view class="content">主要内容区域</view>
<view class="fixed-bottom {{ isNight ? 'night-mode' : 'day-mode' }}"></view>