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
相关产品推荐
相关产品推荐

