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

Vue.js中Delete按钮点击意外触发Save方法的异常求助

问题:Vue模态框中点击Delete按钮意外触发Save方法及函数不存在报错

在Vue.js项目的EditInstruction模态框里有两个按钮:Delete Instruction(绑定deleteInstruction方法)和Save Instruction(绑定saveEditInstruction方法)。点击Delete按钮时,控制台先输出deleteInstruction的执行日志,随后会意外触发saveEditInstruction方法。尝试过重命名方法、调整方法顺序、禁用Save按钮、清除浏览器缓存等操作,问题依旧;将save方法重命名为saveEditInstruction后,还出现_ctx.saveEditInstruction is not a function的报错。


相关代码及日志

1. EditInstruction模态框按钮代码

<!-- SUBMIT/ delete BUTTONS -->
<div class="flex items-center gap-8">           
    <button class="btn-warning mt-4" @click="this.deleteInstruction(editInstruction)">Delete Instruction</button>
    <button type="submit" class="btn-primary mt-4" @click='saveEditInstruction'>Save Instruction</button>
</div>

2. deleteInstruction方法代码

deleteInstruction(_instruction){
    console.log('deleteInstruction _instruction.id = %s', _instruction.id)
    this.swalCustom(`Delete ${_instruction.requestpath}?`, `Are you sure you want to delete ${_instruction.requestpath}?`, 'warning', true, true, 'I am sure.', 'Cancel')
    .then(results=>{
        if(results.isConfirmed){
            this.swalLoading('Deleting...')
            _url = 'http://localhost:8000/api/instructions/' + _instruction.id + '/'
            console.log( '_url = %s ', _url)
            setTimeout(()=>{
                getAPI.delete(_url)
                .then(res=>{
                    this.swalSuccess('Deleted')
                    
                })
                .catch(err=>{
                    this.swalError('Error in deleting ')
                    
                })
                this.loadInstructions()
                this.toggleModal('editInstructionModal')
            }, 1000)
        }
    })
},

3. saveEditInstruction方法代码

saveEditInstruction(row){
    console.log('saveEditInstruction()')
    this.swalLoading('Updating Instruction...')
    //check for completeness
    if(true){
        console.log('saveEditInstruction row.id = %s', row.id)
        setTimeout(()=>{
        // POST API FOR ADDING Instruction
        
        getAPI.put('http://localhost:8000/api/instructions/' + row.id + '/', row)
        .then(res=>{

            // SETS MESSAGE FOR RESPONSE
            let message = `Instruction ${row.requestpath} ${row.description} has been successfully added.`

            // DISPLAYS SUCCESS SCREEN/MODAL
            this.swalSuccess(message)
            this.loadInstructions()
            this.toggleModal('editInstructionModal')
        })
        .catch(err=>{
            this.swalError(err)
        })
    }, 1000)
    this.loadInstructions()
    this.toggleModal('editInstructionModal')
    }

},

4. 控制台日志(初始问题)

deleteInstruction _instruction.id = 1
InstructionsTableModal.vue:438 saveEditInstruction()
InstructionsTableModal.vue:442 saveEditInstruction row.id = 1
InstructionsTableModal.vue:330 loadInstructions()
mixins.js:130 

5. 重命名save方法后的报错日志

runtime-core.esm-bundler.js:38 [Vue warn]: Unhandled error during execution of native event handler 
  at <BaseTransition appear=true persisted=false mode=undefined  ... > 
  at <Transition appear="" name="slide-fade" > 
  at <BaseTransition appear=false persisted=false mode=undefined  ... > 
  at <Transition onClose=fn > 
  at <Modal width="w-[38rem]" ref="editInstructionModal" onClose=fn > 
  at <InstructionsTableModal core=true width="w-[48rem]" ref="InstructionsTableModal"  ... > 
  at <TableMx onVnodeUnmounted=fn<onVnodeUnmounted> ref=Ref< Proxy(Object) {validate: ƒ, formatPrice: ƒ, formatPriceIntl: ƒ, formatDateTime: ƒ, …} > > 
  at <RouterView> 
  at <App>
warn2 @ runtime-core.esm-bundler.js:38
logError @ runtime-core.esm-bundler.js:212
handleError @ runtime-core.esm-bundler.js:204
callWithErrorHandling @ runtime-core.esm-bundler.js:158
callWithAsyncErrorHandling @ runtime-core.esm-bundler.js:164
invoker @ runtime-dom.esm-bundler.js:339
runtime-core.esm-bundler.js:218 Uncaught TypeError: _ctx.saveEditInstruction is not a function
    at InstructionsTableModal.vue:160:36
    at runtime-dom.esm-bundler.js:1450:16
    at callWithErrorHandling (runtime-core.esm-bundler.js:155:22)
    at callWithAsyncErrorHandling (runtime-core.esm-bundler.js:164:21)
    at HTMLFormElement.invoker (runtime-dom.esm-bundler.js:339:9)
(anonymous) @ InstructionsTableModal.vue:160
(anonymous) @ runtime-dom.esm-bundler.js:1450
callWithErrorHandling @ runtime-core.esm-bundler.js:155
callWithAsyncErrorHandling @ runtime-core.esm-bundler.js:164
invoker @ runtime-dom.esm-bundler.js:339
tablemx:1 Uncaught (in promise) Error: A listener indicated an asynchronous response by returning true, but the message channel closed before a response was received

解决方案

1. 解决Delete按钮触发Save方法的问题

问题根源是Delete按钮触发了表单默认提交行为:Save按钮为type="submit",点击Delete按钮时,浏览器会默认触发表单submit事件,进而执行Save相关逻辑。

修复步骤:

  • 给Delete按钮添加type="button",明确它不是提交按钮;
  • Vue模板中调用方法无需加this.,直接写方法名:
<button type="button" class="btn-warning mt-4" @click="deleteInstruction(editInstruction)">Delete Instruction</button>

2. 解决_ctx.saveEditInstruction is not a function报错

该报错通常由以下原因导致,对应修复方式:

  • 方法定义位置错误:确认saveEditInstruction是定义在组件的methods选项中,而非computed或外部代码块;
  • 拼写/缓存问题:检查方法名拼写(大小写一致),重启开发服务器避免缓存残留;
  • 参数传递不匹配:模板中调用saveEditInstruction未传参,但方法定义需要row参数,修改模板传递当前编辑对象:
<button type="submit" class="btn-primary mt-4" @click='saveEditInstruction(editInstruction)'>Save Instruction</button>

或者在方法内部直接使用组件的editInstruction数据,去掉参数:

saveEditInstruction(){
    const row = this.editInstruction;
    // 后续逻辑保持不变
}

3. 额外优化建议

  • 规范表单提交逻辑:使用@submit.prevent阻止表单默认提交行为,统一处理保存逻辑:
<form @submit.prevent="saveEditInstruction(editInstruction)">
    <!-- 表单内容 -->
    <div class="flex items-center gap-8">           
        <button type="button" class="btn-warning mt-4" @click="deleteInstruction(editInstruction)">Delete Instruction</button>
        <button type="submit" class="btn-primary mt-4">Save Instruction</button>
    </div>
</form>
  • 修正异步操作顺序:saveEditInstruction中loadInstructions和toggleModal原本在setTimeout外部,会在API请求完成前执行,导致数据更新不及时,需移到then回调内部:
saveEditInstruction(row){
    console.log('saveEditInstruction()')
    this.swalLoading('Updating Instruction...')
    if(true){
        console.log('saveEditInstruction row.id = %s', row.id)
        setTimeout(()=>{
            getAPI.put('http://localhost:8000/api/instructions/' + row.id + '/', row)
            .then(res=>{
                let message = `Instruction ${row.requestpath} ${row.description} has been successfully updated.`
                this.swalSuccess(message)
                this.loadInstructions()
                this.toggleModal('editInstructionModal')
            })
            .catch(err=>{
                this.swalError(err)
            })
        }, 1000)
    }
},

内容的提问来源于stack exchange,提问作者Ali Vleotsky

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 06:05:34