1
This article will record and imitate an el-card component, which will help you better understand the specific working details of the wheel of Ele.me ui. This article is another article in the elementui source code learning and imitation series. I will continue to update and imitate other components when I am free. The source code is on github, you can pull it down, npm start to run, and comments are helpful for better understanding. The github warehouse address is as follows: https://github.com/shuirongshuifu/elementSrcCodeStudy

My humble opinion

Regarding the card card component, generally in use, it is mainly the interaction effect of card , such as the shadow effect. Ele.me officially provides card the component not only controls the timing of shadow appearance by passing parameters, but also provides a card header slot. Good or good, but generally not used, because the card content is basically written by yourself, if you still use the header slot, you may need more /deep/ To control the style, it is better to rewrite and package one by yourself

After I watched the el-card component, I also packaged a my-card component, which did not add the original header slot #header, but added some interactive effects. The following effects:

  • When the shadow appears (original function)

    • Mouse hover appears
    • always appear
    • does not appear
  • Mouse hover card moves up slightly
  • Mouse hover card to zoom in
  • The mouse hover card is reversed (that is, one more slot="back" slot is used to pass the content on the back)
  • And the style variables that control the front and back cardStyle and backCardStyle

Let's take a look at the renderings

renderings

Do you have any good recording gif software you can share with me. The gif recorded by my software is not very good.

Low-frequency knowledge points used in components

perspective Attribute: Indicates the distance between what we see and the z=0 plane, and can do 3D position transformation perspective effect

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

backface-visibility:hidden Attribute: Specifies that the element is hidden when its back is facing the viewer

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

The idea is to overlap the two divs to be displayed by positioning, one of which is first rotated around the Y axis by a certain angle, and then matched with backface-visibility:hidden to hide it first. When the mouse is hovering, the entire rotation will have an invisible and visible effect, and the flip animation will have it.

this.$slots Attribute: The object that stores the slot, which can store the named slot or the default ordinary slot.

For example, if the external transmission <div slot="back">背面的内容</div> then console.log("this.$slots", this.$slots); you can see whether it is passed in the slot. In this example, it can be used to determine whether to turn on the flip card mode, and then dynamically add the class name through the array usage of :class to achieve the above effect diagram

You can print it out to understand, this is very simple.

code using components

 <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>

packaged component code

 <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>
As for css compatibility, you can add the suffix of the browser manufacturer yourself.

Summarize

  • Copy and paste, and the effect will appear.
  • If there is a little help for you, please give a star on github
  • Because it is a series of articles, your encouragement is the driving force for our creation ^_^

水冗水孚
1.1k 声望585 粉丝

每一个不曾起舞的日子,都是对生命的辜负