uni-app 未配置 "renderer" : "native" 时使用 preload 预加载页面并调用 this.$scope.eventChannel.on 会报错
uni-app 未配置 “renderer” : “native” 时使用 preload 预加载页面并调用 this.$scope.eventChannel.on 会报错
| 开发环境 | 版本号 | 项目创建方式 |
|---|---|---|
| Mac | macOS 11.2.3 | HBuilderX |
测试过的手机
- iphone 12
- MI 8
示例代码:
配置
{
"renderer": "native"
}
文件 /pages/popup/index
<template>
<view class="mask" @click="onClose" />
</template>
<script>
export default {
onShow() {
uni.showToast({
title: `typeof eventChannel.on = ${typeof this.$scope.eventChannel?.on}`,
icon: 'none'
})
},
methods: {
onClose(e) {
e.stopPropagation()
uni.navigateBack()
}
}
}
</script>
<style lang="scss" scoped>
.mask {
flex: 1;
width: 750rpx;
}
</style>
App.vue 文件
<script>
import Vue from 'vue'
export default Vue.extend({
mpType: 'app',
onLaunch() {
uni.preloadPage({ url: '/pages/popup/index' })
}
})
</script>
操作步骤:
参考代码
预期结果:
云端打包和真机调试一致,不报错
实际结果:
云端打包后, this.$scope.eventChannel.on 报错
bug描述:
真机调试没问题,云端打包后,相同代码提示报错
去掉 uni.preloadPage 或使用纯nvue项目 再云打包, this.$scope.eventChannel.on正常
页面都是nvue,经过反复打包测试,缩小配置范围,发现如果配置了 纯nvue项目 this.$scope.eventChannel.on 正常, 如果没配置,则异常。
更多关于uni-app 未配置 "renderer" : "native" 时使用 preload 预加载页面并调用 this.$scope.eventChannel.on 会报错的实战教程也可以访问 https://www.itying.com/category-93-b0.html
关单吧
// 规避 nvue 不支持 this.getOpenerEventChannel() 方法, 在 App.vue 的 onLaunch 中生命周期中注入
uni.getOpenerEventChannel = that => that.$scope.eventChannel
// 页面 or 组件内使用
// 发送数据
uni.getOpenerEventChannel(this).emit(‘change’, ‘some info’)
// 接收数据
uni.getOpenerEventChannel(this).on(‘change’, data => {
console.log(data)
})
更多关于uni-app 未配置 "renderer" : "native" 时使用 preload 预加载页面并调用 this.$scope.eventChannel.on 会报错的实战教程也可以访问 https://www.itying.com/category-93-b0.html
这里我的答复有问题,这里只规避了getOpenerEventChannel 获取不到的问题
查看官网说是支持 this.getOpenerEventChannel() 实际是有问题的
改问题按照说明配置并且云打包后必现,为了排查问题,跟踪检查调整配置花了2天时间,一个功能完全没关系的配置,竟然会影响到云打包后的功能,我是万万没想到的。
异常触发条件
manifest.json 没有勾选 纯nvue项目
页面是 .nvue 后缀
页面采用 uni.preloadPage 做了预加载
页面使用 this.$scope.eventChannel.xx // 为了规避 this.getOpenerEventChannel() 无效
ps:堪比 Dio 上天堂的要求
这个页面为何这么设计
我希望有个能有个全面覆盖的预加载的页面,并且可以通过 uni.xxx 直接唤起,并且能做数据通信(全局弹窗/全局评论)
这样我可以通过覆盖 uni.showTast 和 uni.showModal 等方法改造全局弹窗
然后同 eventChannel 做数据通信避免项目中到处注册全局事件的麻烦
如果不采用 preloadPage,实际测试在安卓下快速频繁的反复打开,画面会闪烁
有官方能确认下这个问题不?
下个版本会修复nvue不支持 getOpenerEventChannel 的问题
你说的undefined的问题,需要一个可重现的测试工程,不排除支持getOpenerEventChannel后,就自动修复了此问题,因为getOpenerEventChannel里边会容错this.$scope.eventChannel 不存在的情况
这是一个在混合渲染模式(未配置 "renderer": "native")下的兼容性问题。当使用 uni.preloadPage 预加载页面时,在云端打包后,预加载页面的 eventChannel 对象可能未正确初始化。
问题分析:
- 在混合渲染模式下,预加载机制与纯 nvue 项目存在差异
- 预加载页面时,
this.$scope.eventChannel可能为 undefined 或未包含完整的 API - 真机调试与云端打包的环境差异导致了行为不一致
解决方案:
在 onShow 生命周期中添加空值检查:
onShow() {
if (this.$scope?.eventChannel?.on) {
uni.showToast({
title: `typeof eventChannel.on = ${typeof this.$scope.eventChannel.on}`,
icon: 'none'
})
} else {
// 处理 eventChannel 不可用的情况
console.warn('eventChannel is not available in preloaded page')
}
}
替代方案: 如果必须使用预加载功能,建议配置为纯 nvue 项目:
{
"renderer": "native"
}

