项目实训 - Scene-UI - 编写card

Card源码

Card的html结构如下:

<div ref="el" class="scene-card">
    <div v-if="$slots.header || header" class="scene-card-head">
        <slot name="header">{{ header }}</slot>
    </div>
    <div class="scene-card-body" :style="bodyStyle">
        <slot></slot>
    </div>
</div>

当用户没有提供header或header插槽则不会渲染第二行的div。

对于卡片的阴影的控制在组件挂载完成时,读取props.shadow,根据不同的情况改变card模板的style:

onMounted(()=>{
      let card: HTMLElement = el.value!;
      // 对不同的卡片出现时机设置不同的阴影效果
      if(shadowTime === 'always')
        card.style.boxShadow = "0px 12px 32px 4px rgba(0, 0, 0, .04), 0px 8px 20px rgba(0, 0, 0, .08)"
      if(shadowTime === 'hover'){
        // 获取旧的 class
        let oldClassName = card.getAttribute('class')
        card.setAttribute('class',oldClassName+' scene-card-hover')
        // 设置过度效果
        card.style.transition = "box-shadow 0.5s"
      }
})

完整代码——card.vue:

<template>
  <div ref="el" class="scene-card">
    <div v-if="$slots.header || header" class="scene-card-head">
        <slot name="header">{{ header }}</slot>
    </div>
    <div class="scene-card-body" :style="bodyStyle">
        <slot></slot>
    </div>
  </div>
</template>

<script lang='ts'>
import {defineComponent, onMounted, ref} from 'vue'
import {cardProps} from './card'
import '../../styles/global.css'

export default defineComponent({
  name:'scene-card',
  props:cardProps,
  setup(props,{emit,attrs,slots,expose}){
    // 卡片阴影出现的时机
    const shadowTime = props.shadow;
    // 卡片元素
    const el = ref<HTMLElement>()

    onMounted(()=>{
      let card: HTMLElement = el.value!;
      // 对不同的卡片出现时机设置不同的阴影效果
      if(shadowTime === 'always')
        card.style.boxShadow = "0px 12px 32px 4px rgba(0, 0, 0, .04), 0px 8px 20px rgba(0, 0, 0, .08)"
      if(shadowTime === 'hover'){
        // 获取旧的 class
        let oldClassName = card.getAttribute('class')
        card.setAttribute('class',oldClassName+' scene-card-hover')
        // 设置过度效果
        card.style.transition = "box-shadow 0.5s"
      }
    })
    
    return {
      el
    }
  }
})
</script>
<style scoped>
.scene-card{
  display: inline-flex;
  flex-direction: column;
  border-radius: var(--scene-border-radius);
  border: var(--scene-border-size) solid var(--scene-color-light-gray);
  overflow: hidden;
  box-sizing: border-box; /** 设置宽高为加上border与padding的宽高 */

  font-size: var(--scene-font-size);
  font-family: var(--scene-font-family);
  letter-spacing: var(--scene-letter-spacing);
}
.scene-card-hover:hover{
  box-shadow: var(--scene-box-shadow)
}
.scene-card-head{
  padding: 10px 20px;
  border-bottom: var(--scene-border-inner-size) solid var(--scene-color-light-gray);
  box-sizing: border-box;
  flex-grow: 0; /** 不占据剩余空间 */
}
.scene-card-body{
  padding: 20px;
  flex-grow: 1; /** 占据所有的剩余空间 */
}
</style>

完整代码——card.ts

export const cardProps = {
    header:{
        type:String,
    },
    shadow:{// 显示阴影的时机
        type:String,
        default: 'always',
        validator(val: string){
            return ['always','hover','never'].includes(val);
        }
    },
    bodyStyle:{//卡片的 body 的样式 object — { padding: '20px' }
        type:Object
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Sunburst7

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值