Vue3组件中实现图标点击后的条件式bgColor渲染
Vue3 点赞/点踩组件状态样式问题解决
我正在开发一个包含点赞(thumbs-up)和点踩(thumbs-down)图标的Vue3组件,需求是:点击任一图标时,该图标放大、填充颜色,同时顶部标题消失。目前已实现点击图标隐藏标题的功能,但无法根据图标是否被点击的状态,为共享ButtonIcon组件的bgColor属性设置对应值。
状态说明
- 初始状态:未点击图标时,顶部标题显示,两个图标均为透明背景、70×70px尺寸
- 当前问题:点击图标后标题消失,但图标样式未按预期变化
- 期望效果:点击的图标变为90×90px尺寸,填充#d64ba1颜色,未点击的图标保持初始样式
现有代码
父组件模板
<template v-slot:main> <div class="feedbackComponent"> <div class="feedback-content"> <label v-if="!hideText" class="title">Appointment Confirmed!</label> <label class="subtitle">How would you rate your experience?</label> <div> <ButtonIcon symbol="thumbs-up" @click="handleFeedback('up')" bgColor="transparent; width: 70px; height: 70px; stroke-width: 1px" /> <ButtonIcon symbol="thumbs-down" bgColor="transparent; width: 70px; height: 70px; stroke-width: 1px" @click="handleFeedback('down')" /> </div> </div> </div> </template>
父组件脚本
<script> import ModalLayout from "@/components/Shared/ModalLayout.vue"; import ButtonIcon from '../Shared/ButtonIcon.vue'; export default { name: 'ScheduleTourFeedback', components: { ModalLayout, ButtonIcon, }, data() { return { selected: null, hideText: false, } }, methods: { handleFeedback(feedback) { this.selected = feedback this.$emit('feedback-clicked', true); this.handleClick(); }, handleClick() { this.hideText = true; }, }, } </script>
ButtonIcon组件代码
<template> <a @click="onClick" :style="backgroundColor" :class="text ? 'TextIcon' : ''"> {{ text }} <i :data-feather="symbol" :class="type ? 'btn-white' : 'btn-continue'" :style="backgroundColor" /> </a> </template> <script> import feather from 'feather-icons' export default { name: 'ButtonIcon', props: { bgColor: String, symbol: String, disabled: Boolean, type: String, text: String, }, computed: { backgroundColor() { let bgColor = this.bgColor ? this.bgColor : '#d64ba1' return 'background: ' + bgColor + ';' + 'border-radius: 24px;' } }, mounted() { feather.replace() }, data() { return {} }, methods: { onClick() { this.$emit('onClick') }, }, } </script> <style scoped> .btn-continue { padding: 8px 10px; gap: 10px; width: 37px; height: 37px; position: relative; background: #d64ba1; border-radius: 24px; color: white; flex: none; order: 0; flex-grow: 0; } .btn-white { padding: 8px 10px; gap: 10px; width: 45px; height: 45px; position: relative; background: white; border-radius: 24px; color: black; border: 2px solid #000; flex: none; order: 0; flex-grow: 0; } .TextIcon { display: flex; align-items: center; justify-content: center; width: 95px; } a { color: #fff; } </style>
解决方案
1. 父组件实现条件样式绑定
利用selected变量判断当前选中的图标,给bgColor绑定三元表达式,动态切换样式:
<ButtonIcon symbol="thumbs-up" @click="handleFeedback('up')" :bgColor="selected === 'up' ? 'transparent; width: 90px; height: 90px; stroke-width: 1px; fill: #d64ba1' : 'transparent; width: 70px; height: 70px; stroke-width: 1px'" /> <ButtonIcon symbol="thumbs-down" :bgColor="selected === 'down' ? 'transparent; width: 90px; height: 90px; stroke-width: 1px; fill: #d64ba1' : 'transparent; width: 70px; height: 70px; stroke-width: 1px'" @click="handleFeedback('down')" />
2. 修复ButtonIcon组件的样式拼接问题
原组件的backgroundColor计算属性错误地将包含width、height的bgColor拼到background:后面,导致样式失效。修改为直接拼接所有样式:
computed: { backgroundColor() { const baseStyle = 'border-radius: 24px;' if (this.bgColor) { return `${this.bgColor}; ${baseStyle}` } return `background: #d64ba1; ${baseStyle}` } }
3. 可选优化:改用对象形式传递样式(更易维护)
如果觉得字符串拼接样式不够清晰,可以改用对象形式:
- 父组件定义样式对象:
<script> export default { data() { return { selected: null, hideText: false, defaultIconStyle: { background: 'transparent', width: '70px', height: '70px', 'stroke-width': '1px' }, activeIconStyle: { background: 'transparent', width: '90px', height: '90px', 'stroke-width': '1px', fill: '#d64ba1' } } }, // ...其他代码 } </script>
- 修改父组件模板的样式绑定:
<ButtonIcon symbol="thumbs-up" @click="handleFeedback('up')" :bgStyle="selected === 'up' ? activeIconStyle : defaultIconStyle" /> <ButtonIcon symbol="thumbs-down" @click="handleFeedback('down')" :bgStyle="selected === 'down' ? activeIconStyle : defaultIconStyle" />
- 更新ButtonIcon组件的props和样式绑定:
<template> <a @click="onClick" :style="[{ borderRadius: '24px' }, bgStyle]" :class="text ? 'TextIcon' : ''"> {{ text }} <i :data-feather="symbol" :class="type ? 'btn-white' : 'btn-continue'" :style="bgStyle" /> </a> </template> <script> export default { props: { bgStyle: Object, // 修改为对象类型 // ...其他props }, // 移除原来的backgroundColor计算属性 // ...其他代码 } </script>
内容的提问来源于stack exchange,提问作者Appu
相关产品推荐
相关产品推荐

