Vue表单提交页面自动刷新问题:如何实现Axios无刷新提交?
问题:Vue表单提交时页面自动刷新,如何实现无刷新提交?
代码问题分析
你的代码里存在两处问题,可能导致页面刷新或逻辑异常:
- 重复绑定提交事件:表单已经通过
v-on:submit.prevent="pemesanan"阻止了默认提交行为并绑定了提交方法,但提交按钮又额外绑定了@click="pemesanan",这会导致pemesanan方法被执行两次,虽然prevent理论上阻止了页面刷新,但冗余绑定可能引发意外。 - 未定义变量导致报错:
makeToast方法中使用了this.toastCount,但在data里没有声明该变量,执行时会抛出错误,可能中断后续逻辑。
修复方案
1. 移除按钮上的重复点击绑定
保留表单的submit.prevent绑定,去掉按钮的@click事件,避免方法重复执行:
修改后的表单及按钮代码:
<form v-on:submit.prevent="pemesanan"> <!-- 其他表单内容 --> <button type="submit" class="btn btn-success"> <b-icon-cart></b-icon-cart>Pesan </button> </form>
2. 补充缺失的变量定义
在data中添加toastCount变量:
data() { return { product:{}, pesan:{}, toastCount: 0, // 添加这一行 items:[ {text:'Home', href:'/'}, {text:'Foods', href:'/food'}, {text:'Food Order', href:'#'} ] } },
可选优化:修改按钮类型
如果想彻底避免表单默认提交的风险,可以将按钮的type改为button,同时把提交逻辑完全放在click事件中(此时需要移除表单的submit绑定):
<form> <!-- 其他表单内容 --> <button type="button" class="btn btn-success" @click="pemesanan"> <b-icon-cart></b-icon-cart>Pesan </button> </form>
完整修改后的组件代码(关键部分)
Template部分
<template> <div class='food-detail'> <NavbarTab /> <div class="container"> <div class="row mt-5"> <div class="col"> <b-breadcrumb :items="items" ></b-breadcrumb> </div> </div> <div class="row mt-3"> <div class="col-sm"> <img :src="'../assets/images/'+product.gambar" :alt="product.gambar" class="img-fluid"> </div> <div class="col-sm"> <form v-on:submit.prevent="pemesanan"> <h2><strong>{{ product.nama }}</strong></h2> <hr> <h4>Harga: <strong>Rp. {{ product.harga }}</strong></h4> <label for="textarea-small">Jumlah:</label> <CounterComponent v-model="pesan.jumlah_pemesanan"/> <label for="textarea-small">Keterangan:</label> <b-form-textarea v-model="pesan.keterangan" id="textarea-small" size="sm" placeholder="Pedas, Nasi Setengah, Kuah di Pisah dll ..." ></b-form-textarea> <button type="submit" class="btn btn-success"> <b-icon-cart></b-icon-cart>Pesan </button> </form> </div> </div> </div> </div> </template>
Script部分
<script> import NavbarTab from '@/components/NavbarTab.vue'; import CounterComponent from '@/components/CounterComponent.vue'; import axios from 'axios'; export default { name:"FoodDetailView", components:{ NavbarTab, CounterComponent }, data() { return { product:{}, pesan:{}, toastCount: 0, items:[ {text:'Home', href:'/'}, {text:'Foods', href:'/food'}, {text:'Food Order', href:'#'} ] } }, methods: { setProduct(){ axios .get("http://localhost:3000/products/" + this.$route.params.food_id) .then((response)=>{this.product = response.data ; console.log(this.$route.params.food_id)}) .catch((error)=>{console.log(this.$route.params.food_id);console.error(error)} ); }, pemesanan(){ this.pesan.product = this.product; axios .post('http://localhost:3000/keranjangs', this.pesan) .then(()=>{ this.makeToast(true); console.log("sukses") }) .catch((err)=>console.error(err)); }, makeToast(append = false) { this.toastCount++ this.$bvToast.toast(`This is toast number ${this.toastCount}`, { title: 'BootstrapVue Toast', autoHideDelay: 5000, appendToast: append }) } }, mounted() { this.setProduct() }, } </script>
内容的提问来源于stack exchange,提问作者Kentaro Madison
相关产品推荐
相关产品推荐

