如何在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)"
为什么原来的方法报错?
- Vue3中通过
ref获取的子组件是组件实例,不是DOM元素,所以没有toggleClass方法(这是jQuery的方法,原生JS也没有)。 - 直接操作DOM不符合Vue的响应式思想,通过props传递状态才是组件通信的标准方式,更易维护和扩展。
内容的提问来源于stack exchange,提问作者volume one
相关产品推荐
相关产品推荐

