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

如何在Vue中为子组件动态添加.selected类?

解决方案:父组件控制子组件选中状态

核心思路是父组件维护选中状态,通过 props 传递给子组件,子组件根据状态绑定样式,完全把选中逻辑放在父组件,保证灵活性。

1. 修改子组件 Contact.vue

子组件只负责接收状态、展示内容和触发点击事件,不处理样式逻辑:

<template>
  <!-- 根据父组件传入的 isSelected 绑定类 -->
  <div 
    style="cursor: pointer" 
    :class="{ selected: isSelected }"
    @click="handleClick"
  >
    <p>{{ Contact.Forename }}</p>
    <p>{{ Contact.Surname }}</p>
  </div>
</template>

<script>
export default {
  props: {
    Contact: {
      type: Object,
      required: true
    },
    // 新增:接收父组件传递的选中状态
    isSelected: {
      type: Boolean,
      default: false
    }
  },
  emits: ['contact-click'], // 定义触发的事件
  setup(props, context) {
    function handleClick() {
      // 点击时通知父组件,传递当前联系人数据
      context.emit('contact-click', props.Contact)
    }

    return { handleClick }
  }
}
</script>

<style scoped>
/* 可选:在子组件里定义选中样式,或者父组件全局定义 */
.selected {
  background-color: #e5f3ff;
  border-left: 4px solid #2196f3;
}
</style>

2. 修改父组件 Parent.vue

父组件维护选中状态,控制子组件的isSelected props:

单选场景(每次只能选中一个)

<template>
  <ol>
    <li v-for="(Contact, index) in Contacts" :key="Contact.id">
      <Component-Contact 
        :Contact="Contact"
        <!-- 传递选中状态:当前联系人ID和选中ID匹配则为true -->
        :is-selected="selectedContactId === Contact.id"
        <!-- 监听子组件的点击事件,更新选中状态 -->
        @contact-click="handleContactClick"
      />
    </li>
  </ol>
</template>

<script>
import ComponentContact from '../components/Contact.vue'
import { ref, onMounted } from 'vue'
import axios from 'axios'

export default {
  components: { ComponentContact },
  setup() {
    const Contacts = ref([])
    // 维护选中的联系人ID(单选)
    const selectedContactId = ref(null)

    // 子组件点击时更新选中ID
    function handleContactClick(contact) {
      // 点击已选中的则取消选中,否则切换到当前
      selectedContactId.value = selectedContactId.value === contact.id ? null : contact.id
      // 这里可以同时处理你的 onSelected 逻辑
      // onSelected({ FullName: `${contact.Forename} ${contact.Surname}` })
    }

    async function fetchContacts() {
      const Result = await axios.get(`/api/contacts`)
      Contacts.value = Result.data
    }

    onMounted(() => {
      fetchContacts()
    })

    return {
      Contacts,
      selectedContactId,
      handleContactClick
    }
  }
}
</script>

多选场景(可选中多个)

如果需要支持多选,只需要把selectedContactId改成数组:

// 父组件内修改
const selectedContactIds = ref([])

function handleContactClick(contact) {
  const id = contact.id
  if (selectedContactIds.value.includes(id)) {
    // 已选中则移除
    selectedContactIds.value = selectedContactIds.value.filter(item => item !== id)
  } else {
    // 未选中则添加
    selectedContactIds.value.push(id)
  }
}

模板里的is-selected改成:

:is-selected="selectedContactIds.includes(Contact.id)"

为什么原来的方法报错?

  1. Vue3中通过ref获取的子组件是组件实例,不是DOM元素,所以没有toggleClass方法(这是jQuery的方法,原生JS也没有)。
  2. 直接操作DOM不符合Vue的响应式思想,通过props传递状态才是组件通信的标准方式,更易维护和扩展。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 03:23:19