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

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>

关键说明

  1. 插槽使用:通过#front和#back命名插槽,父组件可以传入任意HTML或Vue组件作为正反面内容,完全适配你的复杂面板需求。
  2. 状态管理:用内部isFlipped维护翻转状态,避免直接修改props;initialFlipped支持设置初始翻转状态。
  3. 锁定功能:lockable属性开启锁定功能,内部isLocked控制是否允许翻转,同时提供toggleLock方法供外部调用切换锁定状态。
  4. 3D翻转优化:添加perspective和transform-style: preserve-3d实现真实的3D翻转效果,backface-visibility: hidden确保翻转时背面不可见。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 14:01:36