Vue.js 3通用翻转卡片组件开发问题求助
Vue通用翻转卡片组件实现方案
核心改进点
- 用**插槽(Slot)**替代Object类型props,支持传入任意复杂的正反面内容
- 修正props单向数据流问题,内部维护翻转状态
- 添加锁定翻转的可选功能
- 优化CSS实现更真实的3D翻转效果
修改后的FlipCard.vue组件
<template> <div class="flip-card-container" @dblclick="toggleCard"> <div class="flip-card" :class="{ flipped: isFlipped, locked: isLocked }"> <div class="flip-card-front"> <slot name="front"></slot> </div> <div class="flip-card-back"> <slot name="back"></slot> </div> </div> </div> </template> <script> export default { name: "FlipCard", props: { // 初始翻转状态 initialFlipped: { type: Boolean, default: false }, // 是否开启锁定翻转功能 lockable: { type: Boolean, default: false } }, data() { return { isFlipped: this.initialFlipped, isLocked: false }; }, methods: { toggleCard() { if (this.lockable && this.isLocked) return; this.isFlipped = !this.isFlipped; }, // 供外部调用的锁定/解锁切换方法 toggleLock() { this.isLocked = !this.isLocked; } } }; </script> <style scoped> .flip-card-container { perspective: 1000px; /* 开启3D透视效果 */ display: inline-block; margin: 5px; } .flip-card { position: relative; width: 150px; height: 175px; transition: transform 0.4s ease; transform-style: preserve-3d; cursor: pointer; box-shadow: 9px 10px 22px -8px rgba(209,193,209,.5); border-radius: 7px; } .flip-card.flipped { transform: rotateY(180deg); } .flip-card.locked { cursor: not-allowed; opacity: 0.8; } .flip-card-front, .flip-card-back { position: absolute; width: 100%; height: 100%; backface-visibility: hidden; /* 翻转时隐藏背面 */ border-radius: 7px; padding: 20px; box-sizing: border-box; display: flex; flex-direction: column; justify-content: center; align-items: center; } .flip-card-front { background-color: #51aae5; color: #fff; } .flip-card-back { background-color: #e65f51; color: #fff; transform: rotateY(180deg); } </style>
父组件使用示例
<template> <div> <!-- 基础使用:传入自定义正反面内容 --> <FlipCard> <template #front> <div id="planflex"> <div class="block"> <h2>{{ action_id }}</h2> </div> <div class="block"> <img :src="require(`../assets/legos/2x${size}${color}.png`)" alt="legos" id="lego"> </div> <div class="block" :id="action_id" @click="choose"> <h3>{{ actor }}</h3> </div> </div> </template> <template #back> <div> <h3>卡片背面</h3> <p>这里可以放置任意自定义内容</p> </div> </template> </FlipCard> <!-- 带锁定功能的卡片 --> <FlipCard lockable initialFlipped="true" ref="lockableCard"> <template #front> <h2>可锁定卡片正面</h2> </template> <template #back> <h2>可锁定卡片背面</h2> </template> </FlipCard> <button @click="$refs.lockableCard.toggleLock">切换锁定状态</button> </div> </template> <script> import FlipCard from './FlipCard.vue'; export default { components: { FlipCard }, data() { return { action_id: "A001", size: "2", color: "blue", actor: "测试角色" }; }, methods: { choose() { console.log("点击了正面区块"); } } }; </script> <style> /* 自定义区块样式 */ .block { margin-bottom: 10px; } .block h2, .block h3 { margin: 0; } #lego { width: 60px; height: 60px; } </style>
关键说明
- 插槽使用:通过
#front和#back命名插槽,父组件可以传入任意HTML或Vue组件作为正反面内容,完全适配你的复杂面板需求。 - 状态管理:用内部
isFlipped维护翻转状态,避免直接修改props;initialFlipped支持设置初始翻转状态。 - 锁定功能:
lockable属性开启锁定功能,内部isLocked控制是否允许翻转,同时提供toggleLock方法供外部调用切换锁定状态。 - 3D翻转优化:添加
perspective和transform-style: preserve-3d实现真实的3D翻转效果,backface-visibility: hidden确保翻转时背面不可见。
内容的提问来源于stack exchange,提问作者Bilal
相关产品推荐
相关产品推荐

