'Uncaught TypeError: this.xhr.upload.addEventListener is not a function'解决方案

解决方案

https://github.com/nuysoft/Mock/issues/127

我的解决方案是使用了greper提供的mockjs-x

image-20210422130849038

问题描述

问题发生在Ant Design Vue Pro整合vue-simple-uploader时。

在选择上传文件后,控制台爆出了Uncaught TypeError: this.xhr.upload.addEventListener is not a function错误。

image-20210422130526879

image-20210422130604237

发生时的状态

当前日期是2021/04/22。

Ant Design Vue Pro的commit记录为:2f663728bfdba21a9b89a4a4a5698ae802087b61

image-20210422130258391

vue-simple-uploader的版本为:0.7.6

image-20210422130404783

解决过程

解决方案一搜就搜到了:

Axios + mockjs: request.upload.addEventListener is not a function 的原因和解决办法

查错

不过还是没搞明白为什么出错,所以自己研究下。

image-20210422131303875

image-20210422131317749

压缩好的代码肯定看不懂。所以去node_modules里找到vue-simple-uploader,去看它的源代码。

image-20210422131501522

源代码入口是index.js

image-20210422131706514

image-20210422131651789

可以看到,Uploader组件是从./components/uploader.vue导入的。而uploader.vue又是导入了simple-uploader.js

去搜一下的话,发现就是vue-simple-uploader作者的另一个项目。

image-202104221318584013

有兴趣可以去看看。不过我们先直接把项目里用到vue-simple-uploader的地方换成用源代码。

1
2
3
4
5
6
// 原来的
// import uploader from 'vue-simple-uploader'
// const Uploader=uploader.Uploader

// 使用源代码
import Uploader from 'vue-simple-uploader/src/components/uploader'

再次上传文件,可以看到新的报错信息。

image-20210422132242866

注意,变成了chunk.js,点进去看看:

image-20210422132328732

原来是simple-uploader里的一个chunk.js出错了。

分析

MockJS Ajax拦截原理

image-20210422132723086

其实已经很清楚了,MockJS会覆盖原生的XMLHttpRequest,所以chunk.js里new的已经不是真正的XMLHttpRequest了。

image-20210422133127851

而github的issue里较前面的解决方案也很清楚,无论是哪种方式都是在原型链上动手脚。

解决

第一次尝试

发现这个issue已经是2016年的了,目前Mockjs的版本为1.1.0,所以怀疑官方是不是已经解决了。

image-20210422134609264

不过要注意,不知道什么原因,ant design pro vue使用的不是mock而是mockjs2。

image-20210422134838564

Mockjs官方是nuysoft的Mock,而mockjs2是sendya的Mock,但是sendya的是从nuysoft的fork出来的,所以我们先尝试下换成mockjs试试。

image-20210422135101885


答案是:

image-20210422135922976

没有

第二次尝试

注意,这里是在第一次的尝试的基础上改,也就是说仍然用的mockjs而不是mockjs2。

github上说是在node_modules/mockjs/dist/mock.js的8308行加上这句代码(跟之前博客里看到的一样):

1
MockXMLHttpRequest.prototype.upload = xhr.upload;

图片

mockjs2的代码位置有一些变化。


不过这么做了以后,我的网页又不知道出了什么错,就一直在转圈的页面,控制台也不报错。应该是代码里出现了死循环了

既然不行,我就放弃了。而且其实就算能成功,我也不建议这么改

因为node_modules是不会上传到git上的,这也就意味着别人如果下载了这个项目,npm install后他也要去node_modules改,不太合适。

第三次尝试

既然官方没解决,就只能用其它人的了。

image-20210422144322868

如上,npm i mockjs-x --save后,替换所有mockjs成mockjs-x就好。

image-20210422144513241

image-20210422144934383

成功!!!

总结

问题的出现原因就是Mockjs覆盖了XMLHttpRequest导致其它使用XHR的代码出错。


个人很感谢greper,但说实话,使用mockjs-x这种方式也不太完美。单纯为了修复一个bug去使用另一个包。这样的话,mockjs官方有更新时就比较麻烦。

准备去寻找一下其它方式。。。