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

8 回复

关单吧 // 规避 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 对象可能未正确初始化。

问题分析:

  1. 在混合渲染模式下,预加载机制与纯 nvue 项目存在差异
  2. 预加载页面时,this.$scope.eventChannel 可能为 undefined 或未包含完整的 API
  3. 真机调试与云端打包的环境差异导致了行为不一致

解决方案: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"
}
回到顶部