小程序 当从A页面跳走后再跳回时 A页面子组件的数据重新加载的几种实现方式

65 阅读3分钟

前提

当前正在显示的页面,处于栈顶位置。

navigateTo()跳转:前一页保留,后一页压栈

navigateBack()跳回:前一页出栈,后一页回栈顶

A页面navigateTo()跳转B页面,A页面保留在栈内,B页面压入栈顶,显示B页面。

B页面navigateBack()跳回A页面,B页面弹出栈顶,A页面回栈顶,显示A页面。

正文

当从A页面跳走后再跳回时,A页面子组件的数据重新加载的几种实现方式,具体取决于你的业务场景和组件设计:

  1. 利用页面生命周期触发组件更新

页面跳回时会触发 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 });
        }
      })
    }
  }
})
  1. 组件监听页面显示状态(推荐) 组件可以通过 页面栈 监听自身所在页面的显示状态,当页面从隐藏变为显示时自动刷新。

实现步骤:

  • 组件 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);
  }
})
  1. 使用数据监听触发刷新

如果组件的数据依赖于页面传递的属性(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() {
      // 重新加载数据
    }
  }
})
  1. 组件主动判断自身是否可见(进阶)

通过 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)

如有不足 欢迎指点~