7***@qq.com
7***@qq.com
  • 发布:2020-12-08 12:06
  • 更新:2020-12-15 17:51
  • 阅读:820

Vendor核心库中参数处理错误问题

分类:uni-app

问题描述
头条小程序下,使用$emit触发事件,我们时直接在 event.detail 对象取参数,但在uni核心库转换时会进行参数处理,导致我们必须使用 event.detail.args 来转换后取参数,我们覆盖了 this.$scope['triggerEvent'] 的写法。
uni中时这么写的:

Vue.prototype.$emit = function(event) {  
    if (this.$scope && event) {  
      this.$scope['triggerEvent'](event, {  
        __args__: toArray(arguments, 1)  
      });  
    }  
    return oldEmit.apply(this, arguments)  
  };

我们覆盖后:

this.$scope['triggerEventTemp'] = this.$scope['triggerEvent'];  
this.$scope['triggerEvent'] = function () {}  

// 覆盖是为了保证 arguments 不被转换成数组  
Vue.prototype.$emit = function(event) {  
    if (this.$scope && event) {  
      this.$scope['triggerEventTemp'](...arguments);  
    }  
    return oldEmit.apply(this, arguments)  
  };

但是我们发现uni转换的时候有bug,不知是为了避免问题还是,具体见下图

复现步骤
image
这里如果是自定义事件,则会去看是否能取到 args ,如果取不到直接取 event.detail,按照问题描述里我们覆盖后的写法,这个时候 event.detail值是正常的。

image
但是在 vendor 中的 handleEvent 中,会进行处理后的参数判断,这里 params 在自定义事件时,我们覆盖后,得到的是一个对象,符合预期,和Vue中原声 $emit 调用一致,但是在 ret.push 时会进行类型判断,如果不是数组,会置空。

结论:
按照上面的描述,那么自定义事件兜底去取 event.detail 的值,那就是没有意义的,即使取到如果不是数组,那么置空传参就丢失了。

系统信息:
头条小程序

补充信息
[可选]
[根据你的分析,出现这个问题的原因可能在哪里?]

2020-12-08 12:06 负责人:DCloud_UNI_GSQ 分享
已邀请:
DCloud_UNI_GSQ

DCloud_UNI_GSQ

“导致我们必须使用 event.detail.args 来转换后取参数” 这个问题在微信小程序平台是否存在?
能否提供一个相关事件用法的测试示例

  • 7***@qq.com (作者)

    微信小程序平台没出现,但是头条小程序出现了,因为你们在头条小程序这里$emit处理上,会去调 this.$scope 里面的 $triggerEvent,然后你们把 传给 $emit 的参数暴力转成了一个名叫 args 传了进去,导致我们在触发事件的时候,无论传一个参数还是多个参数,都得到的是一个数组,然后在自定义事件的时候,你们会去event.detail.args 拿你们暴力处理的传入的参数,拿不到就去 event.detail里面取,但是你们在最后又判断了拿到的这个参数是否是数组,如果不是数组格式,那么就置空数组,就导致我们拿不到预期的参数;这是有问题的,公司代码,我没办法提供你demo,你可以自己本地测一下,必现的问题。


    另外:报一个内存泄漏的Bug

    如果使用 Image 标签引入图片的话,在H5端页面内会出现内存泄漏

    该用 Img 标签就不会。必现

    2020-12-15 21:56

  • 7***@qq.com (作者)

    纠正:微信小程序不是没有出现,是我们没有去测试

    2020-12-15 21:56

  • 7***@qq.com (作者)

    以上说到的除了内存泄漏的问题,都是和 vendor.js 中的逻辑有关,可以直接定位

    2020-12-15 22:05

  • DCloud_UNI_GSQ

    回复 7***@qq.com: 能否提供单独的测试工程

    2020-12-16 10:43

  • 7***@qq.com (作者)

    回复 DCloud_UNI_GSQ: 是你们Vendor里面的代码有问题,强制转换成了__args__的数组形式,另外自定义事件的参数处理问题我都在上面说的很清楚了,你看下你们的代码一眼就看出问题了,好好测测吧,好多硬伤

    2020-12-16 11:07

  • DCloud_UNI_GSQ

    回复 7***@qq.com: 能否提供一下相关的测试工程啊

    2020-12-16 11:11

  • DCloud_UNI_GSQ

    回复 DCloud_UNI_GSQ: 就看一下你的写法而已

    2020-12-16 11:12

  • DCloud_UNI_GSQ

    回复 7***@qq.com: 目前的单元测试和自动化测试确实存在遗漏,还望提供具体的示例,将会补充到相关测试中。

    2020-12-16 11:15

  • 7***@qq.com (作者)

    回复 DCloud_UNI_GSQ: 好,代码没办法给你组织,你直接在单测里面切到头条小程序的单测用例;然后



    1. this.$emit( 'handleTest', { a: 1, b: 2 } )

    2. 你在 $emit 的回调中,通过 event.detail 看去到的参数是对象吗,如果不是对象,那就是我说的那个问题。


    然后原因是你们打包之后的 vendor.js 文件中的 9906 行的代码对传入的参数无论单个还是多个都强行转成了你们自己命名的数组


    这样说,你看下代码应该很清楚了

    2020-12-16 11:44

  • DCloud_UNI_GSQ

    回复 7***@qq.com: 好的,外层是直接写的 @handleTest="xxx" 还是 @handleTest="xx.xx" 这种?

    2020-12-16 11:48

  • 7***@qq.com (作者)

    回复 DCloud_UNI_GSQ: 外层都可以,只要是自定义事件就行

    2020-12-16 12:52

  • DCloud_UNI_GSQ

    回复 7***@qq.com: 目前测试的结果是@handleTest="handleTest",handleTest方法内打印event就是{ a: 1, b: 2 },和你描述的问题相符吗?

    2020-12-16 15:23

该问题目前已经被锁定, 无法添加新回复