Vue3点击事件中第二个条件执行两次致v-if失效问题求助
Vue3点击事件中状态反复切换的问题解决
在Vue3项目里,点击按钮时同时调用scanAction方法和修改scan.played状态,会出现scan.played先变为true随即变回false的情况,导致v-if="scan.played"无法正常生效。相关代码如下:
<div class="col-md-6" v-if="scan.played" @click="scanAction(scan.id, 'stop'); scan.played = !scan.played"> <i class="btn fas fa-stop"></i> </div>
data() { return { scanList: {}, played: false } },
async scanAction(id, string) { await this.$store.dispatch('axiosPost', {url: `/scans/${id}/${string}`, formData: { } }).then(response => { if (response.data.status === 200) { this.getData() } if (response.data.status === 'error') { return this.$swal.fire({ position: 'center', icon: 'error', title: 'مشکل در داده های ورودی', showConfirmButton: false, timer: 1500 }) } }) },
问题原因
核心问题出在scanAction里的this.getData():该方法会重新获取scanList数据,新获取的scan对象会覆盖原有对象,而新对象的played属性会回到初始的false状态。模板中直接在点击事件里修改scan.played,后续数据更新会覆盖这个修改,看起来像是状态被切换了两次,本质是数据更新导致的状态重置。
解决方案
方案一:将状态修改移到请求回调,确保数据更新后保持状态
修改模板,点击事件仅调用scanAction并传入当前scan对象:
<div class="col-md-6" v-if="scan.played" @click="scanAction(scan.id, 'stop', scan)"> <i class="btn fas fa-stop"></i> </div>
修改scanAction方法,在getData完成后重新定位目标scan并修改状态:
async scanAction(id, string, currentScan) { try { const response = await this.$store.dispatch('axiosPost', { url: `/scans/${id}/${string}`, formData: {} }) if (response.data.status === 200) { await this.getData() // 找到更新后的scan对象并设置状态 const updatedScan = this.scanList.find(item => item.id === id) if (updatedScan) { updatedScan.played = false } } else if (response.data.status === 'error') { this.$swal.fire({ position: 'center', icon: 'error', title: 'مشکل در داده های ورودی', showConfirmButton: false, timer: 1500 }) } } catch (error) { console.error(error) } }
同时,确保getData返回的每个scan对象都带有played属性,可在获取数据后手动添加:
async getData() { const data = await this.$store.dispatch('getScanList') this.scanList = data.map(item => ({ ...item, played: false })) }
方案二:单独管理播放状态,避免数据更新覆盖
将played状态从scan对象中剥离,用独立对象记录每个scan的播放状态:
data() { return { scanList: [], scanPlayStatus: {} // 键为scan的id,值为播放状态 } }, async getData() { const data = await this.$store.dispatch('getScanList') this.scanList = data // 初始化状态,保留已有状态 data.forEach(item => { if (!this.scanPlayStatus.hasOwnProperty(item.id)) { this.scanPlayStatus[item.id] = false } }) }
修改模板和点击事件:
<div class="col-md-6" v-if="scanPlayStatus[scan.id]" @click="scanAction(scan.id, 'stop')"> <i class="btn fas fa-stop"></i> </div>
修改scanAction方法,直接操作独立的状态对象:
async scanAction(id, string) { try { const response = await this.$store.dispatch('axiosPost', { url: `/scans/${id}/${string}`, formData: {} }) if (response.data.status === 200) { await this.getData() this.scanPlayStatus[id] = false } else if (response.data.status === 'error') { this.$swal.fire({ position: 'center', icon: 'error', title: 'مشکل در داده های ورودی', showConfirmButton: false, timer: 1500 }) } } catch (error) { console.error(error) } }
内容的提问来源于stack exchange,提问作者sanaz baghban
相关产品推荐
相关产品推荐

