Vue3卡片(Card)

可自定义设置以下属性:

  • 卡片宽度(width),类型:number | string,默认 'auto'
  • 是否有边框(bordered),类型:boolean,默认 true
  • 卡片右上角的操作区域(extra),类型:string | slot,默认 ''
  • 卡片的尺寸(size),类型:'default' | 'small',默认:'default'
  • 卡片标题(title),类型:string | slot,默认 ''
  • 标题区域自定义样式(headStyle),类型:CSSProperties,默认:{}
  • 内容区域自定义样式(bodyStyle),类型:CSSProperties,默认:{}

效果如下图:在线预览




创建卡片组件Card.vue

ts 复制代码
<script setup lang="ts">
import { ref, computed, onMounted } from 'vue'
import type { CSSProperties } from 'vue'
interface Props {
  width?: number|string // 卡片宽度
  bordered?: boolean // 是否有边框
  extra?: string // 卡片右上角的操作区域 string | slot
  size?: 'default'|'small' // 卡片的尺寸
  title?: string // 卡片标题 string | slot
  headStyle?: CSSProperties //	标题区域自定义样式
  bodyStyle?: CSSProperties // 内容区域自定义样式
}
const props = withDefaults(defineProps<Props>(), {
  width: 'auto',
  bordered: true,
  extra: '',
  size: 'default',
  title: '',
  headStyle: () => { return {} },
  bodyStyle: () => { return {} }
})
const cardWidth = computed(() => {
  if (typeof props.width === 'number') {
    return props.width + 'px'
  }
  return props.width
})
const headRef = ref() // 声明一个同名的模板引用
const showHead = ref(1)
onMounted(() => {
  showHead.value = headRef.value.offsetHeight
})
</script>
<template>
  <div
    class="m-card"
    :class="{'bordered': bordered, 'm-small-card': size === 'small'}"
    :style="`width: ${cardWidth};`">
    <div class="m-card-head" :style="headStyle" v-if="showHead">
      <div class="m-head-wrapper" ref="headRef">
        <div class="u-title">
          <slot name="title">{{ title }}</slot>
        </div>
        <div class="u-extra">
          <slot name="extra">{{ extra }}</slot>
        </div>
      </div>
    </div>
    <div class="m-card-body" :style="bodyStyle">
      <slot></slot>
    </div>
  </div>
</template>
<style lang="less" scoped>
.bordered {
  border: 1px solid #f0f0f0;
}
.m-card {
  font-size: 14px;
  color: rgba(0, 0, 0, 0.88);
  line-height: 1.5714285714285714;
  position: relative;
  background: #ffffff;
  border-radius: 8px;
  text-align: left;
  .m-card-head {
    display: flex;
    justify-content: center;
    flex-direction: column;
    min-height: 56px;
    margin-bottom: -1px;
    padding: 0 24px;
    color: rgba(0, 0, 0, 0.88);
    font-weight: 600;
    font-size: 16px;
    background: transparent;
    border-bottom: 1px solid #f0f0f0;
    border-radius: 8px 8px 0 0;
    .m-head-wrapper {
      width: 100%;
      display: flex;
      align-items: center;
      .u-title {
        display: inline-block;
        flex: 1;
        overflow: hidden;
        white-space: nowrap;
        text-overflow: ellipsis;
      }
      .u-extra {
        margin-inline-start: auto;
        font-weight: normal;
        font-size: 14px;
      }
    }
  }
  .m-card-body {
    padding: 24px;
    border-radius: 0 0 8px 8px;
  }
}
.m-small-card {
  .m-card-head {
    min-height: 38px;
    padding: 0 12px;
    font-size: 14px;
  }
  .m-card-body {
    padding: 12px;
  }
}
</style>

在要使用的页面引入

其中引入使用了 Vue3栅格(Grid)

ts 复制代码
<script setup lang="ts">
import Card from './Card.vue'
</script>
<template>
  <div>
    <h1>Card 卡片</h1>
    <h2 class="mt30 mb10">基本使用</h2>
    <Card title="Default size card" :width="300">
      <template #extra><a href="#">more</a></template>
      <p>card content</p>
      <p>card content</p>
      <p>card content</p>
    </Card>
    <h2 class="mt30 mb10">小尺寸卡片</h2>
    <Card size="small" title="Small size card" :width="300">
      <template #extra><a href="#">more</a></template>
      <p>card content</p>
      <p>card content</p>
      <p>card content</p>
    </Card>
    <h2 class="mt30 mb10">在灰色背景上使用无边框的卡片</h2>
    <div style="display: inline-block; background: #ececec; padding: 30px;">
      <Card title="Card title" :bordered="false" :width="300">
        <p>Card content</p>
        <p>Card content</p>
        <p>Card content</p>
      </Card>
    </div>
    <h2 class="mt30 mb10">自定义标题和内容区域样式</h2>
    <Card
      title="Default size card"
      :width="300"
      :headStyle="{ fontSize: '18px', color: '#fff', backgroundColor: '#52c41a'}"
      :bodyStyle="{ fontSize: '16px', color: '#fff', backgroundColor: '#faad14'}">
      <template #extra><a href="#">more</a></template>
      <p>card content</p>
      <p>card content</p>
      <p>card content</p>
    </Card>
    <h2 class="mt30 mb10">内部卡片</h2>
    <Card title="Card title" :width="360">
      <p style="font-size: 14px; color: rgba(0, 0, 0, 0.85); margin-bottom: 16px; font-weight: 500;">
        Group title
      </p>
      <Card title="Inner card title">
        <template #extra>
          <a href="#">More</a>
        </template>
        Inner Card content
      </Card>
      <Card title="Inner card title" :style="{ marginTop: '16px' }">
        <template #extra>
          <a href="#">More</a>
        </template>
        Inner Card content
      </Card>
    </Card>
    <h2 class="mt30 mb10">栅格卡片</h2>
    <div style="background-color: #ececec; padding: 20px;">
      <Row :gutter="16">
        <Col :span="8">
          <Card title="Card title" :bordered="false">
            <p>card content</p>
          </Card>
        </Col>
        <Col :span="8">
          <Card title="Card title" :bordered="false">
            <p>card content</p>
          </Card>
        </Col>
        <Col :span="8">
          <Card title="Card title" :bordered="false">
            <p>card content</p>
          </Card>
        </Col>
      </Row>
    </div>
    <h2 class="mt30 mb10">简洁卡片</h2>
    <Card :width="300">
      <p>Card content</p>
      <p>Card content</p>
      <p>Card content</p>
    </Card>
  </div>
</template>
相关推荐
glustful8 小时前
企业内部审计项目管理 系统开源(springboot+vue3)
vue3·springboot
RuoyiOffice19 小时前
SpringBoot3+Vue3 会议室预订系统:时段冲突三模式检测 + 会前定时提醒与 cancelByBiz
spring boot·vue3·flowable·消息中心·spring boot 3·会议室·时段冲突
燐妤2 天前
中老年智能健康管理项目
python·ai·pycharm·vue3·fastapi·项目开发·健康
gis开发之家3 天前
《Vue3 从入门到大神50篇》Vue3 源码详解(二十):生命周期钩子源码解析 —— onMounted / onUpdated 如何实现?
前端·javascript·前端框架·vue3·vue3源码
java1234_小锋10 天前
Vue3专题 - 响应式基础
vue·vue3·响应式
春波petal12 天前
Vue3防抖搜索:从Lodash到customRef全解析
vue.js·vue3·防抖搜索
濮水大叔13 天前
不必把 Vue3 写成“麻花”:从状态碎片到对象协作,重新理解 Zova 的前端心智模型
前端·typescript·vue3·ioc·tsx·zova
听风34714 天前
智扫通机器人智能客服系统
vue3·fastapi·智能客服·agent项目
熊猫钓鱼>_>16 天前
ArkTS 基础入门:从零搭建第一个交互页面
华为·架构·交互·ts·harmonyos·arkts·鸿蒙
gis开发之家16 天前
《Vue3 从入门到大神40篇》Vue3 源码详解(十):diff 算法全解析 —— 为什么 Vue3 比 Vue2 更快?
javascript·算法·typescript·前端框架·vue3·vue3源码