辛宝Otto

辛宝Otto 的玄酒清谈

北漂前端程序员儿 / 探索新事物 / Web Worker 主播之一/内向话痨
xiaoyuzhou
email

uni-app 使用 $on $emit 進行跨頁信息傳遞

uni-app 使用 $on $emit 进行跨页信息传递

uni-app 使用 $on $emit 进行跨页信息传递,附 Vue23 写法

最近看到 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 實現頁面信息傳遞,供遇到相似問題的用戶參考。

載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。