微信小程序中页面间的通信是指不同页面之间的数据传递、状态同步或交互操作,常见于多页面协作场景。根据通信方向和场景不同,主要有以下几种实现方式:
一、基于页面跳转的参数传递
1. 正向传递(A页面到B页面)
通过URL参数携带数据,在跳转时传递给目标页面,适用于简单数据的一次性传递。
// A页面跳转代码(声明式导航) <navigator url="/pages/B/B?id=100&name=测试">跳转到B页面</navigator> // A页面跳转代码(编程式导航) wx.navigateTo({ url: '/pages/B/B?id=100&name=测试' }) // B页面接收参数(在onLoad生命周期中) Page({ onLoad(options) { console.log(options.id); // 100 console.log(options.name); // 测试 } })
注意:参数值需避免特殊字符,若包含中文或特殊符号,建议使用encodeURIComponent编码后传递。
2. 反向传递(B页面到A页面)
从子页面返回父页面时,通过页面栈获取父页面实例,直接调用其方法传递数据。
// B页面返回并传递数据 Page({ backToA() { // 获取当前页面栈 const pages = getCurrentPages(); // 上一页(A页面)实例 const prevPage = pages[pages.length - 2]; // 调用A页面的方法传递数据 prevPage.receiveData('从B页面返回的数据'); // 返回上一页 wx.navigateBack(); } }) // A页面定义接收数据的方法 Page({ data: { dataFromB: '' }, receiveData(data) { this.setData({ dataFromB: data }); } })
适用于表单提交后刷新列表、选择器返回选择结果等场景。
二、全局数据共享机制
1. 全局变量(app.js)
在app.js中定义全局数据,所有页面通过getApp()访问,适合简单的全局状态共享。
// app.js中定义 App({ globalData: { userInfo: null, theme: 'light' } }) // 页面中访问和修改 const app = getApp(); // 读取 console.log(app.globalData.theme); // 修改 app.globalData.theme = 'dark';
缺点:数据变化时不会自动通知页面更新,需手动调用setData刷新视图。
2. 状态管理库(如mobx-miniprogram)
通过响应式状态管理库实现跨页面数据同步,适合中大型项目。
// 1. 定义store(store/index.js) import { observable, action } from 'mobx-miniprogram'; export const store = observable({ count: 0, updateCount: action(function(val) { this.count = val; }) }); // 2. 页面A中修改状态 import { store } from '../../store'; store.updateCount(10); // 3. 页面B中监听状态变化 import { createStoreBindings } from 'mobx-miniprogram-bindings'; Page({ onLoad() { this.bindings = createStoreBindings(this, { store, fields: ['count'], actions: ['updateCount'] }); }, onUnload() { this.bindings.destroy(); } })
特点:数据变化时自动更新所有引用页面,实现真正的响应式通信。
三、本地缓存通信
利用小程序的本地缓存API(同步/异步)存储数据,实现跨页面共享,数据可持久化。
// 存储数据(页面A) wx.setStorageSync('userToken', 'abc123'); wx.setStorage({ key: 'userInfo', data: { name: '张三' }, success() { console.log('存储成功') } }); // 读取数据(页面B) const token = wx.getStorageSync('userToken'); wx.getStorage({ key: 'userInfo', success(res) { console.log(res.data.name) } // 张三 });
适用场景:存储登录凭证、用户偏好设置等需长期保留的数据,注意缓存有大小限制(约10MB)。
四、事件总线(EventBus)
通过自定义事件总线实现任意页面间的通信,适合无直接跳转关系的页面。
// 1. 创建事件总线(utils/eventBus.js) class EventBus { constructor() { this.events = {}; } // 订阅事件 on(name, callback) { if (!this.events[name]) this.events[name] = []; this.events[name].push(callback); } // 发布事件 emit(name, data) { if (this.events[name]) { this.events[name].forEach(cb => cb(data)); } } // 取消订阅 off(name, callback) { if (this.events[name]) { this.events[name] = this.events[name].filter(cb => cb !== callback); } } } export default new EventBus(); // 2. 页面A订阅事件 import eventBus from '../../utils/eventBus'; Page({ onLoad() { this.handleMsg = (data) => { console.log('收到消息:', data); }; eventBus.on('msgEvent', this.handleMsg); }, onUnload() { eventBus.off('msgEvent', this.handleMsg); // 页面卸载时取消订阅 } }) // 3. 页面B发布事件 import eventBus from '../../utils/eventBus'; Page({ sendMsg() { eventBus.emit('msgEvent', '来自B页面的消息'); } })
优点:解耦性强,适合复杂页面结构的通信;需注意及时取消订阅避免内存泄漏。
五、各方式适用场景对比
URL参数传递:适合简单数据的正向跳转,如详情页ID传递。
页面栈反向传递:适合子页面返回父页面时传递结果,如选择器组件。
全局变量:适合简单的全局数据共享,如应用配置。
状态管理库:适合中大型项目的复杂状态同步,如购物车数据。
本地缓存:适合持久化数据存储,如登录状态、用户设置。
事件总线:适合无直接关联页面的通信,如跨模块通知。
实际开发中,可根据项目复杂度和具体场景选择合适的方式,复杂场景下可组合多种方式使用。