免费获取学习方案
ARTICLE DETAIL

资讯详情

深耕编程基础知识与建站技术分享的一线实战洞察。

九、uni-app通信方式

九、uni-app通信方式 一、uni-app通信方式汇总通信方式适用场景通信方向数据量持久化优缺点与注意事项Props Events同一页面内的父子组件通信单向父传子/ 单向子传父小 - 中❌ 否最基础。Vue3 组合式 API 中子组件通过defineEmits触发事件父组件通过event监听。URL 参数页面跳转时传递简单数据如 ID、状态值单向父→子小字符串❌ 否最简单。内存开销小。但无法传复杂对象敏感信息如密码不要放 URL 里。EventChannel两个有跳转关系的页面间通信如列表页→详情页双向中对象/数组❌ 否官方推荐。数据不暴露在 URL安全性高。仅适用于uni.navigateTo跳转。全局事件总线任意页面/组件间的跨级通信如修改头像多处更新多向广播中❌ 否最灵活。使用uni.$emit发送uni.$on接收。⚠️ 必须在页面卸载 (onUnload) 时uni.$off移除监听防止内存泄漏。Pinia / Vuex复杂应用的全局状态管理如购物车、登录态双向大❌ 否最规范。集中管理状态Vue3 强烈推荐 Pinia。适合高频共享、多页面依赖的数据。本地存储 (Storage)需要持久化的配置或历史记录如主题色、搜索历史单向中✅ 是最持久。使用uni.setStorageSync存uni.getStorageSync取。数据会一直保留直到用户清理缓存。依赖注入 (Provide/Inject)深层嵌套的组件/页面共享配置单向祖先→后代中❌ 否最优雅。祖先组件provide数据后代组件inject获取避免层层传递 Props。二、Props Events父子组件通信Props Events是 uni-app 中最基础的组件通信方式适用于同一页面内的父子组件之间传递数据。父组件通过 Props 向子组件传值子组件通过触发自定义事件将数据回传给父组件。子组件 (ChildComponent.vue)script setup // 1. 定义 Props接收父组件传值 const props defineProps({ title: { type: String, default: 默认标题 }, count: { type: Number, default: 0 } }); // 2. 定义 Emits声明要触发的事件 const emit defineEmits([update-count, submit]); // 3. 触发事件向父组件传递数据 const handleAdd () { emit(update-count, props.count 1); }; /script template view text{{ title }} - 当前计数: {{ count }}/text button clickhandleAdd点击1/button /view /template父组件 (ParentPage.vue)script setup import { ref } from vue; import ChildComponent from ./ChildComponent.vue; const myCount ref(0); // 4. 监听子组件的事件并处理传回的数据 const handleCountUpdate (newCount) { myCount.value newCount; }; /script template view !-- 5. 绑定 Props 和 监听 Emits -- ChildComponent title我的计数器 :countmyCount update-counthandleCountUpdate / /view /template三、URL 参数页面跳转传参URL 参数适用于传递简单的、非敏感的数据如 ID、状态码是页面跳转之间最简单的传参方式。使用时需要注意以下几点URL 长度有限制小程序端约 1KB不能传大对象。如果参数包含特殊字符如,必须使用encodeURIComponent编码接收时用decodeURIComponent解码。URL 传过来的参数都是字符串数字需要手动转换。发送页 (ListPage.vue)script setup const goToDetail () { const id 1001; const name 张三 李四; // 包含特殊字符 uni.navigateTo({ url: /pages/detail/detail?id${id}name${encodeURIComponent(name)} }); }; /script接收页 (DetailPage.vue)script setup import { ref } from vue; const detailId ref(0); const userName ref(); // 在 onLoad 生命周期中接收参数 const onLoad (options) { // 1. 转换数字类型 detailId.value parseInt(options.id); // 2. 解码特殊字符 if (options.name) { userName.value decodeURIComponent(options.name); } console.log(接收到的参数:, detailId.value, userName.value); }; /script四、EventChannel页面双向通信这是 uni-app 官方推荐的、用于两个有跳转关系的页面之间的通信方式。特别适合“子页面操作完需要把数据带回父页面并刷新”的场景。其核心是通过getOpenerEventChannel()获取通道实例实现父子页面之间的双向数据传递。父页面 (ParentPage.vue)script setup import { ref } from vue; const listData ref([]); const openChildPage () { uni.navigateTo({ url: /pages/child/child, // 1. 监听子页面发来的事件 events: { onChildSubmit: (data) { console.log(收到子页面数据:, data); // 刷新父页面列表 listData.value.push(data); } }, // 2. 跳转成功后向子页面发送数据 success: (res) { res.eventChannel.emit(toChildData, { message: 这是父页面给你的初始数据 }); } }); }; /script子页面 (ChildPage.vue)script setup import { ref, onMounted, getCurrentInstance } from vue; const receivedMsg ref(); const eventChannel ref(null); onMounted(() { // 1. 获取 EventChannel 实例 const instance getCurrentInstance().proxy; eventChannel.value instance.getOpenerEventChannel(); // 2. 监听父页面发来的数据 eventChannel.value.on(toChildData, (data) { console.log(收到父页面数据:, data); receivedMsg.value data.message; }); }); // 3. 子页面操作完成后向父页面回传数据 const submitToParent () { eventChannel.value.emit(onChildSubmit, { id: Date.now(), content: 子页面提交的新数据 }); // 传完数据后返回上一页 uni.navigateBack(); }; /script五、全局事件总线全局事件总线用于任意页面/组件间的跨级通信适合「修改头像后多处需要同步更新」等广播场景。核心 API 包括uni.$on、uni.$emit、uni.$once和uni.$off。1. uni.$on(eventName, callback)持续监听作用注册一个全局事件监听只要事件被触发回调函数就会持续执行。场景监听用户登录状态、全局主题切换等需要反复触发的场景。⚠️ 必须配合uni.$off使用否则会导致内存泄漏。2. uni.$emit(eventName, OBJECT)触发事件作用主动触发一个全局自定义事件并可以携带任意类型的数据Object、String 等。场景在任意页面或组件中当某个业务逻辑完成时如修改了头像向全局广播通知。3. uni.$once(eventName, callback)一次性监听作用注册一个全局事件监听但只触发一次。在第一次触发之后会自动移除该监听器。场景只希望接收一次的通知。比如首次进入 App 时的新手引导弹窗、从 A 页面跳 B 页面只传一次参数。优势触发后自动销毁不需要手动调用uni.$off非常省心。4. uni.$off(eventName, callback)移除监听作用精准移除全局自定义事件的监听器。⚠️核心避坑点传入的回调函数必须与$on时的回调是同一个函数引用。因此千万不要使用匿名函数或箭头函数来注册监听否则将无法被正确移除5. 持续监听与精准移除接收方页面 (PageB.vue)script setup import { ref } from vue; import { onUnload } from dcloudio/uni-app; const userInfo ref(null); // 1. 【关键】将回调定义为具名函数绝对不能写成箭头函数 const handleUserUpdate (data) { console.log(收到全局通知:, data); userInfo.value data; }; // 2. 注册持续监听 uni.$on(global-user-update, handleUserUpdate); // 3. 【关键】页面卸载时精准移除监听防止内存泄漏 onUnload(() { uni.$off(global-user-update, handleUserUpdate); }); /script发送方页面 (PageA.vue)script setup const sendMsg () { // 触发全局事件并携带数据 uni.$emit(global-user-update, { username: 前端大师, avatar: xxx.jpg }); }; /script6. 一次性监听接收方页面 (PageC.vue)script setup // 1. 使用 $once 监听只接收一次 uni.$once(show-newbie-guide, (guideData) { console.log(收到新手引导:, guideData); // 弹出新手引导弹窗... }); // 2. 【注意】$once 触发后会自动移除不需要写 uni.$off /script发送方页面 (App.vue 或任意页面)script setup // 触发一次新手引导事件 uni.$emit(show-newbie-guide, { step: 1 }); /script7. 避坑指南先订阅后发布uni.$on必须在uni.$emit之前执行。如果目标页面还没加载还没执行$on你提前$emit事件就会丢失。拒绝匿名函数uni.$on(event, () {})这种写法会导致uni.$off失效因为每次传入的匿名函数内存地址都不一样。命名规范事件名建议全小写加中划线如user-login-success避免与 uni-app 内置事件冲突。六、依赖注入 (Provide / Inject)这是 Vue3 官方提供的跨层级通信方案。当组件嵌套层级很深比如爷爷 - 爸爸 - 儿子 - 孙子用 Props 一层层传会非常痛苦。provide/inject 允许祖先组件直接跨越中间层向所有后代提供数据。保持响应式如果希望后代组件能响应数据的变化祖先组件提供数据时必须传入ref或reactive包裹的响应式数据。单向数据流后代组件拿到数据后尽量不要直接修改。最佳实践是祖先组件提供“修改数据的方法”后代组件调用方法来修改。祖先组件如 App.vue 或某个根页面 RootPage.vuescript setup import { ref, provide } from vue; // 1. 准备响应式数据 const theme ref(light); // 2. 准备修改数据的方法推荐做法 const toggleTheme () { theme.value theme.value light ? dark : light; }; // 3. 向所有后代提供数据和方法 provide(themeConfig, { currentTheme: theme, toggleTheme: toggleTheme }); /script后代组件无论隔了多少层如 GrandChildComponent.vuescript setup import { inject } from vue; // 1. 注入祖先提供的数据第二个参数是默认值防止祖先没提供时报错 const config inject(themeConfig, { currentTheme: ref(light), toggleTheme: () {} }); // 2. 直接使用数据是响应式的且能调用方法 const changeTheme () { config.toggleTheme(); }; /script template view :classconfig.currentTheme text当前主题: {{ config.currentTheme }}/text button clickchangeTheme切换主题/button /view /template
返回列表