小程序性能优化-预加载
在微信小程序中,数据预加载是提升用户体验的重要优化手段。以下是处理数据预加载的完整方案:
一、预加载的适用场景
- 跳转页面前的数据准备
如从列表页进入详情页前,提前加载详情数据 - 首屏加载后的空闲时间
在首页加载完成后,预加载其他高频页面数据 - 多步骤流程的后续步骤
如电商下单流程中,提前加载支付页面所需数据
二、核心实现方案
1. 全局预加载(App级别)
// app.js
App({
globalData: {
preloadData: {} // 全局缓存池
},
// 预加载方法
preload: function(url, params) {
return new Promise((resolve, reject) => {
wx.request({
url: 'https://api.example.com/' + url,
data: params,
success: (res) => {
this.globalData.preloadData[url] = res.data;
resolve(res);
},
fail: reject
})
})
}
})
2. 页面跳转时预加载
// 列表页 list.js
Page({
onItemTap(e) {
const id = e.currentTarget.dataset.id;
// 在跳转前发起预加载
getApp().preload('detail', { id })
wx.navigateTo({
url: `/pages/detail/detail?id=${id}`
})
}
})
// 详情页 detail.js
Page({
onLoad(options) {
const id = options.id;
const cachedData = getApp().globalData.preloadData[`detail?id=${id}`];
if(cachedData) {
this.setData({ detail: cachedData }) // 使用缓存数据
delete getApp().globalData.preloadData[`detail?id=${id}`] // 清除缓存
} else {
this.fetchData(id) // 常规请求
}
}
})
三、高级优化策略
1. 智能预加载(基于用户行为预测)
// 监控用户停留时间预测跳转
let timer = null;
Page({
onItemHover() {
timer = setTimeout(() => {
this.preloadDetailData()
}, 800) // 悬停800ms触发预加载
},
onItemLeave() {
clearTimeout(timer)
}
})
2. 数据版本控制
// 带版本号的缓存
const cacheWithVersion = {
key: 'detail_1.2.3', // 版本号随API版本更新
data: {...},
expire: Date.now() + 3600000 // 1小时过期
}
3. 请求优先级管理
class RequestQueue {
constructor() {
this.highPriorityQueue = []
this.lowPriorityQueue = []
}
add(request, priority = 'low') {
if(priority === 'high') {
this.highPriorityQueue.push(request)
} else {
this.lowPriorityQueue.push(request)
}
this.process()
}
}
四、性能优化技巧
-
分块预加载
// 分批加载避免卡顿 function chunkPreload(list) { const chunkSize = 3; for(let i=0; i<list.length; i+=chunkSize) { setTimeout(() => { loadChunk(list.slice(i, i+chunkSize)) }, i*200) } }
-
缓存淘汰策略
// LRU缓存控制 const MAX_CACHE_SIZE = 10; function addToCache(key, data) { const keys = Object.keys(getApp().globalData.preloadData); if(keys.length >= MAX_CACHE_SIZE) { delete getApp().globalData.preloadData[keys[0]]; } getApp().globalData.preloadData[key] = data; }
-
预加载状态管理
// 使用全局状态跟踪 const preloadStatus = new Map(); function startPreload(url) { preloadStatus.set(url, 'loading'); wx.request({ // ... success() { preloadStatus.set(url, 'loaded') } }) }
五、调试与监控
1. 性能监控
// 自定义性能打点
const perf = {
start: {},
marks: {},
mark(name) {
this.start[name] = Date.now()
},
measure(name) {
this.marks[name] = Date.now() - this.start[name]
wx.reportAnalytics('preload_perf', this.marks)
}
}
2. 缓存命中率统计
let stats = {
total: 0,
hit: 0
}
function getCache(key) {
stats.total++;
if(cache[key]) {
stats.hit++;
return cache[key]
}
return null
}
六、注意事项
-
流量控制
- 移动网络下限制预加载数据量
- 提供用户可关闭预加载的配置项
-
数据一致性
- 对实时性要求高的数据(如库存)禁用预加载
- 设置合理的缓存过期时间
-
错误处理
function safePreload(url) { return getApp().preload(url) .catch(err => { wx.reportMonitor('preload_failed', 1) return Promise.resolve() // 防止阻断流程 }) }
七、推荐工具
-
自定义预加载管理器
class PreloadManager { constructor() { this.queue = [] this.maxConcurrent = 2 // 最大并发数 } add(task) { this.queue.push(task) this.run() } run() { while(this.running < this.maxConcurrent && this.queue.length) { const task = this.queue.shift() this.running++ task().finally(() => { this.running-- this.run() }) } } }
-
使用 Worker 处理复杂数据
// 在worker中处理大数据 const worker = wx.createWorker('workers/preload.js') worker.postMessage({ type: 'preprocess', data: rawData })
通过合理使用这些技术方案,可以显著提升小程序的流畅度(建议结合具体业务场景调整策略)。在实际项目中建议先通过 wx.getPerformance() API 分析性能瓶颈,再有针对性地实施预加载策略。