前提
当前正在显示的页面,处于栈顶位置。
navigateTo()跳转:前一页保留,后一页压栈
navigateBack()跳回:前一页出栈,后一页回栈顶
例
A页面navigateTo()跳转B页面,A页面保留在栈内,B页面压入栈顶,显示B页面。
B页面navigateBack()跳回A页面,B页面弹出栈顶,A页面回栈顶,显示A页面。
正文
当从A页面跳走后再跳回时,A页面子组件的数据重新加载的几种实现方式,具体取决于你的业务场景和组件设计:
- 利用页面生命周期触发组件更新
页面跳回时会触发 onShow 生命周期(页面从后台切回前台),可以在页面的 onShow 中主动通知子组件重新加载数据。
实现步骤:
- 页面中给子组件定义一个 id 或 selector
- 页面 onShow 时,通过 selectComponent 获取子组件实例,调用组件内的刷新方法
示例代码:
父组件
<child-component id="myChild"></child-component>
Page({
onShow() {
// 页面显示时,触发子组件刷新
const child = this.selectComponent('#myChild');
if (child) {
child.reloadData(); // 调用组件内的刷新方法
}
}
})
子组件
Component({
methods: {
reloadData() {
// 重新加载数据的逻辑
this.fetchData();
},
fetchData() {
// 实际请求数据的方法
wx.request({
url: 'xxx',
success: (res) => {
this.setData({ list: res.data });
}
})
}
}
})
- 组件监听页面显示状态(推荐) 组件可以通过 页面栈 监听自身所在页面的显示状态,当页面从隐藏变为显示时自动刷新。
实现步骤:
- 组件 attached 时,记录当前页面路径
- 监听小程序 onAppShow 事件,判断当前页面是否为组件所在页面
- 若匹配则触发数据刷新
示例代码:
子组件
Component({
data: {
currentPagePath: ''
},
lifetimes: {
attached() {
// 获取当前组件所在页面的路径
const pages = getCurrentPages();
this.setData({
currentPagePath: pages[pages.length - 1].route
});
// 监听小程序显示事件
this.appShowListener = () => {
const currentPages = getCurrentPages();
const currentPage = currentPages[currentPages.length - 1];
// 若当前显示的页面是组件所在页面,则刷新数据
if (currentPage.route === this.data.currentPagePath) {
this.fetchData();
}
};
getApp().onAppShow(this.appShowListener);
},
detached() {
// 组件销毁时移除监听,避免内存泄漏
getApp().offAppShow(this.appShowListener);
}
},
methods: {
fetchData() {
// 重新加载数据
}
}
})
app.js 中需要添加事件管理(全局事件总线)
App({
onLaunch() {
this.appShowCallbacks = [];
},
onShow() {
// 触发所有注册的显示回调
this.appShowCallbacks.forEach(cb => cb());
},
onAppShow(cb) {
this.appShowCallbacks.push(cb);
},
offAppShow(cb) {
this.appShowCallbacks = this.appShowCallbacks.filter(item => item !== cb);
}
})
- 使用数据监听触发刷新
如果组件的数据依赖于页面传递的属性(properties),可以通过监听属性变化触发刷新。
实现步骤:
- 页面跳回时,修改传给子组件的属性值(如时间戳、版本号)
- 组件监听该属性变化,触发数据重新加载
父组件
<child-component refreshKey="{{refreshKey}}"></child-component>
Page({
data: {
refreshKey: 0 // 用于触发刷新的标记
},
onShow() {
// 页面显示时,修改标记值(每次+1)
this.setData({
refreshKey: this.data.refreshKey + 1
});
}
})
子组件
Component({
properties: {
refreshKey: {
type: Number,
value: 0
}
},
observers: {
'refreshKey'(newVal) {
// 监听属性变化,触发数据刷新
this.fetchData();
}
},
methods: {
fetchData() {
// 重新加载数据
}
}
})
- 组件主动判断自身是否可见(进阶)
通过 IntersectionObserver 监听组件是否进入视口,结合页面栈判断是否需要刷新(适合滚动场景)。
示例代码:
子组件
Component({
lifetimes: {
attached() {
this.createIntersectionObserver()
.relativeToViewport()
.observe('.component-root', (res) => {
// 当组件可见比例 > 0 时(进入视口)
if (res.intersectionRatio > 0) {
const pages = getCurrentPages();
const currentPage = pages[pages.length - 1];
// 若当前页面是组件所在页面,则刷新
if (currentPage.route === this.data.currentPagePath) {
this.fetchData();
}
}
});
}
}
})
总结推荐方案
-
简单场景:用页面 onShow 调用组件方法(方案 1)
-
组件复用场景:用全局事件监听(方案 2)
-
数据依赖场景:用属性监听(方案 3)
选择时需注意
-
避免重复请求(可加 loading 状态判断)
-
及时移除事件监听(防止内存泄漏)
-
结合业务场景选择最低成本的方案(如频繁跳转的页面优先方案 2)
如有不足 欢迎指点~