Vue使用axios发送FormData对象导致页面刷新没想到是Live Server的锅
起因和分析过程
本来想写一个简单的在线添加水印的在线页面,然后使用django作为后端,当vue得到文件后将其打包成为FormData对象,然后通过axios发送到后端,但是却意外的发现,页面在发送后自动刷新了,然后在前端就一直无法进行获取数据后的处理,尝试了断点,发现在进行了一次msg==reload
的判定后就会导致调用window.localtion.reload()
页面刷新。
因为这只是一个单独的页面应用,所以,我当时想到了直接给window.localtion给干掉,直接给他指定为了null,但是这会导致vue不可用,然后想到了既然是绑定在window.localtion.reload(),那我直接给这个方法覆盖掉不就行了,然后我将这个方法指定为了null,结果还是不起作用……小聪明失效了。
这有点超出认知了,然后在不停百度中得到的只有一个原因,在使用form表单时没有处理默认提交事件,所以在点击后会进行默认的页面刷新
很有道理,但是我在页面中没有使用使用form表单域和提交的submit,只是使用了input和 button,后面想到不会是button都不允许吧?然后还改成了div来触发。
但是结果还是一样,会自动刷新,于是我使用了e.preventDefault()
,但是结果还是没用。于是我想到不会是vue有什么隐藏的刷新判定吧?于是我将vue给注释掉使用了原生来获取打包FormData对象,然后配合axios发送给后端。
const formData = new FormData();
// 向 FormData 对象添加字段数据
var x = document.querySelectorAll("input")
x[0].addEventListener("change", function (e) {
console.log(e.target.files[0]);
formData.append('file', e.target.files[0]);
console.log(formData);
})
x[1].addEventListener("change", function (e) {
formData.append('text', this.value);
})
document.querySelector(".button").addEventListener("click", function (e) {
e.preventDefault();
axios.post('http://127.0.0.1:8000/watermarkUp', formData, {
headers: { "Content-Type": "multipart/form-data" },
responseType: "json"
})
.then(response => {
var url = response.data.url
console.log(url)
window.open(url)
})
})
但是结果还是会刷新,这个时候我就有点懵了,话说之前也用过FormData对象的这种打包方式,只不过似乎之前确实没有关心过页面是否会刷新,自己已经尽可能规避了formdata可能导致的刷新问题。
就在我想是不是因为FormData这个对象使用的问题?也就是是不是只要发送FormData对象就会导致刷新,我甚至准备换一种传输形式,不适用FormData时,这个时候我叫了我的朋友帮我看看,他说会不会是后端导致的?因为后端返回了重定向等让前端刷新了?
似乎,也不排除,后端使用的是python的django框架,处理代码就不发出来了,发一下返回代码
def fileUp(request):
# 业务代码
return HttpResponse(json.dumps({
"code":"200",
"data":data
}),content_type='application/json; charset=utf-8')
但是,这似乎不可能存在重定向啊,后面为了更加确保又copy了一段返回json数据的代码
def fileUp(request):
return JsonResponse({"data":data})
使用专门的json返回,这总不可能存在什么重定向了吧?
但是已经没用……
嘛了,当我准备打开百度搜索还有那些文件上传形式时,突然想到了我一直都是使用vscode的Live Server扩展来实时查看网页,我从来没有在文件夹直接打开这个文件。
这有啥区别呢,众所周知,LS是把你的目录文件夹挂载成一个服务,这样你才能通过5500端口访问到当前的页面什么的,而直接在文件夹中打开则只存在单个页面,相当于控制变量法,又去掉了一个不确定的因素。
就是这样,单独打开了这个html文件,然后页面没有刷新了!
原理
原理?不知道,或许是LS的某项设置让得到后端处理FormData请求时自动刷新页面,有了解的大佬可以分享一波。反正,这通过“拒绝中间商赚差价”的方式解决了这个未知的问题。还是值得记录的,刚刚百度了一下似乎还没有人提到这个问题,也可能是我自己的问题,然后会把所有代码贴在下面,有兴趣的可以复现一下,主要是分享一下解决问题时想到的一些办法。
django后端估计基本上没有人使用,我觉得那个不是重点,也就是说,可以弄上任意一个后端,然后接收前端发送的formdata中的一个文件,这就会导致页面刷新,记得打开vscode的live server时测试。
代码
<div class="box" id="app">
<h1>水印在线添加</h1>
<div class="check">
<input type="file" @change="handleFileInputChange"><br>
<div class="set">文字<input v-model="text" type="text" name="text" id=""></div>
<div class="set">字体大小<input v-model="fontsize" type="number" placeholder="可选" name="fontsize" id="">
</div>
<div class="set">字体透明度<input v-model="alp" type="number" placeholder="可选" name="alp" id=""></div>
</div>
<button class="button" @click="up">上传</button>
<div class="download">返回地址: {{url}}</div>
</div>
const HelloVueApp = {
el: "#app",
data() {
return {
file: "",
text: "",
fontsize: "",
alp: "",
url:""
}
},
computed: {
},
methods: {
handleFileInputChange(e) {
var file = e.target.files[0]
this.file = file
},
async up() {
// window.preventDefault
// window.location.reload() = ' '
// e.preventDefault()
const formData = new FormData();
// 向 FormData 对象添加字段数据
formData.append('file', this.file);
formData.append('text', this.text);
if (!this.fontsize == "") {
formData.append('fontsize', this.fontsize);
}
if (!this.alp == "") {
formData.append('alp', this.alp);
}
// 使用 axios 发送 POST 请求
await axios.post('http://127.0.0.1:8000/watermarkUp', formData, {
headers: { "Content-Type": "multipart/form-data" },
responseType: "json"
}
)
.then(response => {
this.url = response.data.url
console.log(this.url)
// window.open(response.data.data)
})
.catch(function (error) { // 请求失败处理
console.log(error);
});
console.log("发送完毕");
}
},
mounted() {
}
}
var app = new Vue(HelloVueApp)
然后中间的一切注释也没有删掉证明我确实是使用过禁止默认行为的。
分享一下,有懂得大佬可以说一下具体得原理。