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

Vue JS中点击事件触发组件条件渲染的实现方法

核心原则
  • Vue 官方推荐完全通过响应式数据驱动视图更新,这类条件渲染场景绝对不要直接操作DOM。直接修改DOM属性既无法触发Vue的响应式更新,还会导致业务状态和真实DOM强耦合,后续维护极易出现状态不一致的问题。
  • 你写的代码无法运行,本质是违背了数据驱动的核心思路,同时存在多处语法和API使用错误。
正确实现方案

给列表的每一项维护独立的响应式loading状态,点击时直接修改对应项的状态,Vue会自动完成视图更新,不需要手动操作任何DOM。修正后的可运行代码如下:

<template>
  <!-- v-for 必须绑定唯一key,优先使用数据本身的唯一id,无唯一id时可临时使用索引 -->
  <div v-for="data in list" :key="data.id">
    {{ data.bar }}
    <button @click="handleClick(data)">
      <div v-if="data.loading">
        <Loader />
      </div>
      <div v-else>
        确认操作
      </div>
    </button>
  </div>
</template>

<script setup>
import { Loader } from './components'
import { reactive } from 'vue'

// 初始化列表时给每条数据加上独立的loading状态,用reactive包裹保证属性变更响应式
const list = reactive([
  { id: 1, foo: 'bar', bar: '测试条目', loading: false }
])

const handleClick = (currentItem) => {
  // 直接修改当前条目的响应式状态,Vue自动触发对应视图更新
  currentItem.loading = true
  // 注意setTimeout参数顺序:第一个为回调函数,第二个为延迟毫秒数
  setTimeout(() => {
    currentItem.loading = false
    // 此处写你的业务逻辑,比如接口请求、操作提交等
  }, 3000)
}
</script>

如果不想修改原始列表的数据结构,也可以单独用一个响应式Map/对象存储每个条目id对应的loading状态,逻辑完全一致。

原代码的具体错误点
  • 直接修改DOM的dataset.loading:这个操作不会被Vue的响应式系统捕获,v-if的判断条件不会重新计算,自然不会触发视图更新。
  • setTimeout参数顺序写反:原生setTimeout第一个参数必须是回调函数,第二个参数才是延迟毫秒数,你写的setTimeout(3, () => {})不会按预期延迟执行。
  • 模板语法错误:v-else对应的div标签没有闭合,v-for缺少必填的key属性,会触发Vue编译警告。
  • 事件参数取值错误:@click默认传入的第一个参数是原生事件对象,不是按钮DOM元素,要获取当前点击的列表条目,必须主动将v-for的循环项data作为参数传入回调。
  • 冗余的类型判断:v-if可以直接接收布尔值作为判断条件,不需要把状态转成字符串再和'true'做比较。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 12:09:23