前言
提示:这里可以添加本文要记录的大概内容:
本篇主要是对Uncaught RangeError: Maximum call stack size exceeded
报错的处理解决过程记录。
提示:以下是本篇文章正文内容,下面案例可供参考
一、背景?
当前是vue3+js + element plus
用到的是一个对话框组件
代码如下(示例):
<!-- 对话框内部主要代码 -->
<div>
<el-button color="#255EFF">本地上传并编辑</el-button>
<input type="file" id="config-edit-uploadfile" onChange="fileSelect()">
</div>
<!-- js主要代码 -->
/**
* @fileSelect
*/
const fileSelect = () => {
let file = document.getElementById('config-edit-uploadfile');
console.log("选择文件", file);
if(!file) return;
// file = file.files && file.files[0];
}
二、解决步骤
1.详细触发流程
2.问题探索
堆栈溢出的产生是由于过多的函数调用,导致调用堆栈无法容纳这些调用的返回地址,一般容易在递归中产生。
我们的这个问题,在查阅资料和自己整理综合,发现,应该是:
在点击事件发生的时候,这个input是被包裹在div内部的,所以input的点击事件触发后,通过事件冒泡又触发了div的点击事件,div的点击事件又去触发input的点击事件,input的点击事件再次冒泡触发div的点击事件……如此一来便造成了无限循环,所以报错:Maximum call stack size exceeded。
大多数博主的解决办法是,将input框移到div外部,但是在我们这里是行不通的,可能是背景不同吧。在查看组件源码发现:
后面,我想着,那我为什么不尝试组件库的el-input尼?
于是:
原来的:
<input type="file" id="config-edit-uploadfile" onChange="fileSelect()">
被替换成:
<el-input type="file" id="config-edit-uploadfile" @input="fileSelect()"/>
关于input的onChange事件,改成了el-input的input事件,不明白的可以去官网查看。
我的目的是得到获取的文件,从而实现接下来的操作。当然你们可以有不同的目的,选择不同的方法。
3. 问题解决
代码
<div class="upload">
<el-button color="#255EFF">本地上传并编辑</el-button>
<el-input type="file" id="config-edit-uploadfile" @input="fileSelect()"/>
</div>
/**
* @fileSelect
*/
const fileSelect = () => {
console.log("选择文件")
let file = document.getElementById('config-edit-uploadfile');
console.log("选择文件", file);
if(!file) return;
console.log("file", file.files);
file = file.files && file.files[0];
console.log("file2222", file);
}
总结
提示:这里对文章进行总结:
可能会有人问,为什么button没有绑定点击事件,为什么就触发了input的上传事件尼。原因和实现如下(主要是css的功劳):
.upload {
/deep/.el-input {
display: inline-block;
opacity: 0;
width: 170px;
height: 32px;
cursor: pointer;
position: absolute;
right: 0px;
top: 85px;
}
}
upload类名添加的意义:为了避免css污染,影响到其他的el-input
/ddep/深层遍历找到这组件的类名(我自己的理解,可能说的有点问题,不过意思是找到这个类名就对了)
position: absolute; 相对定位,将我们的文件上传的部分,覆盖住el-button,;
opacity: 0;透明,这样用户就看不到了
》》》》》》》》》》》》》》》》》》》》》》》》未设置透明之前
》》》》》》》》》》》》》》》》》》》》》》》》设置透明之后