前言
Form表单提交不跳转,随便一搜就能了解到有三种解决方案:
第一种是e.preventDefault(),禁止默认事件,禁止跳转;
第二种是使用iframe承载;
第三种是使用ajax,直接请求。
但实践出真知,测试过程中发现第一种方案并不管用,它不仅阻止了跳转,还阻止了表单提交。第三种方案如果需要兼容不支持html5新属性formData的手机的话,是行不通的。考虑到现在绝大多数手机都支持,因此这种方案也是可行的。本文仅记录下用第二种方案来实现过程中遇到的兼容性问题。
什么是enctype
enctype 属性规定在发送到服务器之前应该如何对表单数据进行编码,默认地情况下表单数据会编码为 “application/x-www-form-urlencoded”。就是说,在发送到服务器之前,所有字符都会进行编码(空格转换为 “+” 加号,特殊符号转换为 ASCII HEX 值)。它有以下三个属性值:
值 | 描述 |
---|---|
application/x-www-form-urlencoded | 在发送前编码所有字符(默认) |
multipart/form-data | 不对字符编码。 在使用包含文件上传控件的表单时,必须使用该值。 |
text/plain | 空格转换为 “+” 加号,但不对特殊字符编码。 |
所以application/x-www-form-urlencoded,不能用于文件上传,它的意思是在发送前编码所有字符(默认),只能上传文本格式的文件。而multipart/form-data是指表单数据由多部分构成,既有文本数据,又有文件等二进制数据的意思,这样可以实现多种类型的文件上传,所以我们需要在表单上设置multipart/form-data。
设置表单及iframe承载元素
<form action="/api/common/uploadFile" ref = {uploadForm} method = "post" encType = "multipart/form-data" target = "uploadIframe> <input type={"file"} ref = {uploadFileRef} name="file" accept={"image/*} onChange={upLoadFile} />
<input type={"text"} style={{display: "none"}} name = "userToken" value={"your token"}/>
<input type={"text"} style={{display: "none"}} name = "anotherParmas" value={"your params"}/>
</form>
<iframe style={{display: "none"}} ref={iframeRef} name="uploadIframe"></iframe>
获取表单请求结果
设置好上述元素后,配置表单请求不跳转,利用iframe获取请求结果。
var fileUpIframe = iframeRef.current;
fileUpIframe.onload = fileUpIframe.onreadystatechange = function () {
try {
var data = JSON.parse(fileUpIframe.contentWindow.document.body.innerHTML);
if (data.code === 200) {
Toast.success("文件上传成功!");
} else {
Toast.fail("上传图片失败,请重试!");
}
}catch (err){
console.error(err);
}
}
注意:
若后端将返回的类型是application/json而不是text/html,则取到的返回结果是这种文本
'<pre style="white-space: pre-wrap;word-wrap: break-word;background:#fff;border:none">{"code":200,"msg":"success","data":{"a":1,"b":2}}</pre>';
需要进行处理后方可使用:
reg = /<pre.+?>(.+)<\/pre>/g;
data.match(reg);
data = JSON.parse(RegExp.$1);
问题
以上方案能正确和后端联调并完成数据交互,但在实测过程中发现在安卓(IOS无问题)手机上,按返回键的时候因iframe的存在,会出现多级页面的问题从而使得页面标题栏变化但是页面内容没变化。也就是说按返回键的时候并不能准确的返回,需要按两次返回键才能正确返回到上一页。
解决方案
既然是iframe引起的,那么就采用动态iframe的方式来解决这个问题。也即刚开始不设置iframe,采用原生js来创建一个iframe,与后端完成数据交互后移除这个iframe。
const frameId = "targetFrame";
const fileUpIframe = document.createElement("iframe");
fileUpIframe.id = frameId;
fileUpIframe.name = frameId;
fileUpIframe.style.display = "none";
document.body.appendChild(fileUpIframe);
uploadForm.current.target = frameId;
fileUpIframe.onload = fileUpIframe.onreadystatechange = function () {
try{
let data = fileUpIframe.contentWindow.document.body.innerHTML;
let reg = /<pre.+?>(.+)<\/pre>/g;
data.match(reg);
data = JSON.parse(RegExp.$1);
if (data.code === 200) {
Toast.success("上传成功");
} else {
Toast.fail("上传失败");
}
document.body.removeChild(fileUpIframe);
} catch(err) {
console.error(err);
}
}
uploadForm.current.submit();
上传完毕后获取到数据后,移除掉这个iframe,从而避免了单页面应用存在多级页面的问题。
今天的文章Form表单提交不跳转在hybrd App上的实现分享到此就结束了,感谢您的阅读。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/19932.html