elementui源码学习之仿写一个el-card

简介: elementui源码学习之仿写一个el-card

theme: cyanosis

本篇文章记录一下,仿写一个el-card组件,有助于大家更好理解,饿了么ui的轮子具体工作细节。本文是elementui源码学习仿写系列的又一篇文章,后续空闲了会不断更新并仿写其他组件。源码在github上,大家可以拉下来,npm start运行跑起来,结合注释有助于更好的理解。github仓库地址如下: https://github.com/shuirongshuifu/elementSrcCodeStudy

个人愚见

关于卡片card组件,一般在使用中,主要还是card的交互效果,比如阴影效果。饿了么官方提供的card组件除了通过传参控制阴影出现的时机,额外还提供了一个卡片头部插槽。好是好,不过一般用不到,因为卡片内容基本上都是自己写的,如果还使用头部插槽,可能需要多一些/deep/ 去控制样式,倒不如自己改写封装一个

本人看了饿了么el-card组件以后,也封装了一个my-card组件,没有加入原有的头部插槽#header,不过多加了一些交互效果,整体有以下效果:

  • 阴影出现的时机(原有功能)

    • 鼠标悬浮出现
    • 总是出现
    • 不出现
  • 鼠标悬浮卡片略微上移
  • 鼠标悬浮卡片放大一些
  • 鼠标悬浮卡片反转(即多了一个slot="back"的插槽用于传递背面的内容)
  • 以及控制正面、背面的样式变量cardStyle和backCardStyle

我们先看一下效果图

效果图

111.gif

大家有什么好的录制gif软件可以分享我一下哦。我的这个软件录制出来的gif效果不太好。

组件中所用到的低频知识点

perspective属性:表示咱们看到的与z=0平面的距离,可以做三维位置变换透视效果

官方:https://developer.mozilla.org/zh-CN/docs/Web/CSS/perspective

backface-visibility:hidden属性:指定当元素背面朝向观察者时藏起来

官方:https://developer.mozilla.org/zh-CN/docs/Web/CSS/backface-visibility

实现思路就是将两个要展示的div利用定位重叠在一起,其中一个首先围绕Y轴旋转一定角度,然后搭配 backface-visibility:hidden先藏起啦。鼠标悬浮的时候,整个旋转,就出现不可见到可见的一个效果啦,翻转动画就有喽

this.$slots属性:存放插槽的对象,可以存命名插槽、或者default普通插槽。

比如外界传递<div slot="back">背面的内容</div> 那么console.log("this.$slots", this.$slots); 就可以看到是否传递进来插槽了。本例中可用于判断是否开启翻转卡片模式,然后通过:class的数组用法来动态添加类名,即可实现上述效果图

大家打印一下就明白,这个很简单。

使用组件的代码

<template>
  <div class="box">
    <my-card class="cardClass" shadow="hover">悬浮出阴影</my-card>
    <my-card class="cardClass" shadow="always">始终出阴影</my-card>
    <my-card class="cardClass" shadow="none">没有阴影</my-card>
    <my-card class="cardClass" shadow="hover" isHoverUp>悬浮出阴影上移</my-card>
    <my-card class="cardClass" shadow="always" isHoverUp>始终出阴影上移</my-card>
    <my-card class="cardClass" shadow="none" isHoverUp>没有阴影上移</my-card>
    <my-card class="cardClass" shadow="hover" zoomCard>悬浮出阴影放大</my-card>
    <my-card class="cardClass" shadow="always" zoomCard>始终出阴影放大</my-card>
    <my-card class="cardClass" shadow="none" zoomCard>没有阴影放大</my-card>
    <my-card class="cardClass" :cardStyle="{ padding: 0 }" shadow="hover"
      >使用cardStyle去控制样式,比如这里清除内边距</my-card
    >
    <my-card
      class="cardClass cardClass2"
      :cardStyle="{ background: 'pink' }"
      :backCardStyle="{ background: '#baf' }"
      >悬浮卡片翻转(正面)
      <!-- 当有命名插槽back的时候,自动开启翻转模式 -->
      <div slot="back">背面的内容</div>
    </my-card>
  </div>
</template>

<style lang='less' scoped>
.box {
  display: flex;
  flex-wrap: wrap;
  box-sizing: border-box;
  padding: 24px;
  .cardClass {
    width: 240px;
    margin-right: 24px;
    margin-bottom: 24px;
  }
  .cardClass2 {
    height: 180px;
  }
}
</style>

封装的组件代码

<template>
  <div
    :class="[
      'card-box',
      this.$slots.back ? 'card-reverse' : '',
      zoomCard ? 'card-box-zoom' : '',
    ]"
  >
    <div class="card-content">
      <!-- 当有back命名插槽时,加上frontReverse类名并移除front-side类名,才有反转效果 -->
      <div
        :style="cardStyle"
        :class="[
          this.$slots.back ? 'frontReverse' : 'front-side',
          shadow,
          isHoverUp ? 'isHoverUp' : '',
        ]"
      >
        <!-- 正常情况下普通插槽显示内容即可 -->
        <slot></slot>
      </div>
      <div :style="backCardStyle" class="backReverse" v-if="this.$slots.back">
        <!-- 有命名插槽就显示命名插槽内容,并做类名移除和新增,开启翻转效果 -->
        <slot name="back" />
      </div>
    </div>
  </div>
</template>

<script>
const shadowArr = ["hover", "always", "none"]; // shadow="none"不传递也行的
export default {
  name: "myCard",
  props: {
    cardStyle: {}, // 控制卡片(正面的样式)
    backCardStyle: {}, // 控制背面卡片的样式
    shadow: {
      // 阴影出现时机:鼠标悬浮出现、一直出现、或不出现
      type: String,
      validator(val) {
        // 校验
        if (shadowArr.includes(val)) return true;
        return false;
      },
    },
    isHoverUp: Boolean, // 是否悬浮往上平移一点
    zoomCard: Boolean, // 是否放大卡片(hover时)
  },
  mounted() {
    console.log("this.$slots", this.$slots);
  },
};
</script>

<style lang="less" scoped>
.card-box {
  // background-color: #fff; /* 注意卡片盒子不能加背景色,会挡住旋转样式效果 */
  color: #333;
  perspective: 1000;
  transform-style: preserve-3d;
  transition: all 0.4s;
}
// 加card-box-zoom类名,就整体放大1.08倍
.card-box-zoom:hover {
  transform: scale(1.08);
}
// 中转的用于定位的容器盒子
.card-content {
  position: relative;
  width: 100%;
  height: 100%;
  transition: 0.75s;
  transform-style: preserve-3d;
}
/* 使用front-side类名控制普通状态时的样式 */
.front-side {
  box-sizing: border-box;
  padding: 18px;
  border-radius: 4px;
  border: 1px solid #e9e9e9;
  transition: 0.3s;
}
// 有hover类名时,在hover时,就加阴影
.hover:hover {
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
}
// 有isHoverUp类名时,就在hover时往上移动一点
.isHoverUp:hover {
  transform: translateY(-3px);
}
// 有always类名时,就加阴影
.always {
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
}
/* 使用frontReverse和backReverse类名专门控制卡片反转状态时的样式 */
.frontReverse, // 利用定位使前后面重叠
.backReverse {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  backface-visibility: hidden;
  transform-style: preserve-3d;
  box-sizing: border-box;
  padding: 18px;
  border-radius: 4px;
  border: 1px solid #e9e9e9;
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
}
.frontReverse {
  z-index: 2; // 前面层级抬高
}
.backReverse {
  transform: rotateY(-180deg); // 后面旋转不可见
}
.card-reverse:hover .card-content {
  // hover时候,旋转容器,就会出现,不可见到可见的过程了,翻转动画就有了
  transform: rotateY(180deg);
}
</style>
至于css兼容性的话,大家可以自己加上浏览器厂商的后缀呗

总结

  • 复制粘贴,即可出现效果。
  • 如果对您有一点点帮忙,欢迎github给个star哦
  • 因为是系列文章,您的鼓励是咱创作的动力^_^
相关文章
|
数据处理 Python
|
存储 移动开发 HTML5
SessionStorage 和 LocalStorage 有什么区别?
SessionStorage 和 LocalStorage 有什么区别?
982 3
|
人工智能 前端开发 API
Dify Agent 驱动轻量级 MCPserver:联动 Zapier 实现智能搜索高效数据流转
Dify Agent 驱动轻量级 MCPserver:联动 Zapier 实现智能搜索高效数据流转
Dify Agent 驱动轻量级 MCPserver:联动 Zapier 实现智能搜索高效数据流转
|
存储 编解码 Dart
腾讯开源混元视频生成模型,这效果!太稳了吧!
腾讯开源了HunyuanVideo,这是一个超过130亿参数的视频生成模型,具备高性能的图像-视频联合生成能力。通过创新的模型架构和高效的训练基础设施,HunyuanVideo在视觉质量、运动多样性和文本-视频对齐等方面表现出色,超越了多个现有模型。该项目旨在推动视频生成技术的发展,促进社区交流与创新。
2211 11
腾讯开源混元视频生成模型,这效果!太稳了吧!
|
机器学习/深度学习 数据格式
R1-Omni开源!多模态模型+RLVR,让各模态作用清晰可见
随着 DeepSeek R1 的推出,强化学习在大模型领域的潜力被进一步挖掘。Reinforcement Learning with Verifiable Reward (RLVR) 方法的出现,为多模态任务提供了全新的优化思路,无论是几何推理、视觉计数,还是经典图像分类和物体检测任务,RLVR 都展现出了显著优于传统监督微调(SFT)的效果。
1276 12
|
机器学习/深度学习 人工智能 自然语言处理
Java+机器学习基础:打造AI学习基础
随着人工智能(AI)技术的飞速发展,越来越多的开发者开始探索如何将AI技术应用到实际业务场景中。Java作为一种强大的编程语言,不仅在企业级应用开发中占据重要地位,在AI领域也展现出了巨大的潜力。本文将通过模拟一个AI应用,从背景历史、业务场景、优缺点、底层原理等方面,介绍如何使用Java结合机器学习技术来打造一个AI学习的基础Demo。
750 18
|
存储 安全 数据库
系统网站登录,如何合规传输用户登录密码?
用户登录密码属于用户隐私数据。为防止密码在登录接口中明文传输,提出将密码转换为MD5值再进行传输,并在服务端使用加盐的MD5值进行比对。为进一步提升安全性,建议使用可逆加密算法结合时间戳,确保每次传输的密码值不同。
521 0
|
索引 Python
如何在 Pandas 数据框中添加新列?
【8月更文挑战第30天】
1571 4
|
前端开发
css动画效果(边框流光闪烁阴影效果)
css动画效果(边框流光闪烁阴影效果)
【JAVA进阶篇教学】第九篇:MyBatis-Plus用法介绍
【JAVA进阶篇教学】第九篇:MyBatis-Plus用法介绍