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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 07:05:16