You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vue表单提交页面自动刷新问题:如何实现Axios无刷新提交?

问题:Vue表单提交时页面自动刷新,如何实现无刷新提交?

代码问题分析

你的代码里存在两处问题,可能导致页面刷新或逻辑异常:

  1. 重复绑定提交事件:表单已经通过v-on:submit.prevent="pemesanan"阻止了默认提交行为并绑定了提交方法,但提交按钮又额外绑定了@click="pemesanan",这会导致pemesanan方法被执行两次,虽然prevent理论上阻止了页面刷新,但冗余绑定可能引发意外。
  2. 未定义变量导致报错: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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 14:55:58