DCloud_UNI_OttoJi
DCloud_UNI_OttoJi
  • 发布:2023-12-22 20:14
  • 更新:2025-02-11 18:23
  • 阅读:1446

使用 $on $emit 进行跨页信息传递,附上 vue2 和 vue3 写法

分类:uni-app

最近看到 ask 社区有用户提问如何正确使用 $emit $on 方法实现 uni-app 程序页面之间通信,有用户使用 $on 收不到消息,在这里尝试做个最佳实践的总结,供有相似困惑的用户参考。

谁需要阅读这篇文章

应用级别跨页面通信,处于各种原因,决定使用 $on/$emit 进行数据传递的使用场景。

常见问题场景

从 A 页面跳转到 B 页面,需要携带一部分复杂对象信息。在 A 页面定义 $emit 在 B 页面定义 $on,跳转页面之后,发现 B 页面接受不到事件。退回页面重新跳转就可以收到了。并且有的用户发现可以加 setTimeout 延迟之后可以使用。

这种方式并不可靠,说到底,在 A 页面发出事件的时候,B 页面还没有初始化,自然接受不到相关事件。

这里提供两种方案,供不同业务需求的用户使用。

方案一:先握手再发送

演示代码地址 https://gitcode.net/xiurensha5731/uni-app-questions/-/tree/q/api-emit/src/pages

观察 index 页面和 about 页面。

在 index 页面,也就是 page1 页面,先注册 $on 事件,回调函数时候发送具体数据。

// 这里演示,从 index 跳转到 about 时候,传递信息  
const go = () => {  
  uni.navigateTo({  
    url: "/pages/about/index?msg=hello",  
  });  
};  

onLoad(() => {  
  // 思路是先发注册监听、再发送信息。此时 page2  
  // 跳转后之后才会激活页面,才会收到 on 事件  
  uni.$on("page2Ready", function (data) {  
    console.log("page1 收到 page2 发过来的信息", data);  
    uni.$emit("update", { msg: "页面更新" });  
  });  
});  

onUnload(() => {  
  uni.$off("page2Ready");  
});

在 about 页面,也就是 page2 页面。先注册事件,之后通知 page1 接受信息。

const message = ref("");  

onLoad(() => {  
  uni.$on("update", function (data) {  
    console.log("page2 监听到事件来自 update ,携带参数 msg 为:" + data.msg);  
    message.value = data.msg;  
  });  
  uni.$emit("page2Ready", { msg: "page2 准备好了,你发送吧" });  
});  
onUnload(() => {  
  uni.$off("update");  
});  

完整代码参考上面链接。

方案二:使用 uni.navigateTo 的 events

官方文档地址 https://uniapp.dcloud.net.cn/api/router.html#navigateto
搜索 events 关键字,可以定位到使用方法。

这里也提供线上看运行地址,git 地址 观察 index 页面和 about 页面。

在 index 页面,也就是 page1 页面

// 这里演示,从 index 跳转到 about 时候,传递信息  
const go = () => {  
  uni.navigateTo({  
    url: "/pages/about/index?msg=hello",  
    events: {  
      // 可以接受下一页的通知  
      page1: function (data) {  
        console.log(444, data);  
      },  
    },  
    success: function (res) {  
      // 通过eventChannel向被打开页面传送数据  
      res.eventChannel.emit("page2", { data: "page1 发来的信息" });  
    },  
  });  
};  

在 about 页面,也就是 page2 页面,这里提供 option 和 composition 两种写法。


// vue3 setup 写法  
const message = ref("");  
// vue3 setup 写法  
onLoad(() => {  
  const { proxy } = getCurrentInstance();  
  const eventChannel = proxy.getOpenerEventChannel();  
  eventChannel.emit("page1", { data: "data from test page" });  
  // 监听acceptDataFromOpenerPage事件,获取上一页面通过eventChannel传送到当前页面的数据  
  eventChannel.on("page2", (data) => {  
    console.log(222, data.data);  
    message.value = data.data;  
  });  
});  

// vue2 写法  
// export default {  
//   data() {  
//     return { message: "" };  
//   },  
//   onLoad(option) {  
//     const _this = this;  
//     const eventChannel = this.getOpenerEventChannel();  
//     eventChannel.emit("page1", { data: "data from test page" });  
//     // 监听acceptDataFromOpenerPage事件,获取上一页面通过eventChannel传送到当前页面的数据  
//     eventChannel.on("page2", (data) => {  
//       console.log(222, data.data);  
//       _this.message = data.data;  
//     });  
//   },  
// };

技术总结

上述两种方案,都可以使用 emit 和 on 实现页面信息传递,供遇到相似问题的用户参考。

1 关注 分享
julytian

要回复文章请先登录注册

2***@qq.com

2***@qq.com

方法1:vue3的写法下,编译h5可以正常通信,不会出现必须返回一次才通信,编译成微信小程序的时候就不行了,怎么弄
2025-02-11 18:23