完成首页样式设计:课程卡片组件与样式优化
vp-course-item 是比 vp-item 更复杂的课程信息卡片,包含背景图、标题、子标题、作者头像、点赞统计和标签。本节从组件设计思路出发,完成"大家都在学"区域的四宫格展示,并总结首页整体样式优化的要点。
vp-course-item 组件设计
设计思路
将卡片视为一个整体,分为上下两部分:
┌─────────────────────────┐
│ │
│ 背景图(固定高度) │ ← bg-cover 背景图
│ [标签] │ ← absolute 定位
│ │
├─────────────────────────┤
│ 标题 │ ← font-bold, line-clamp-1
│ 子标题 │ ← text-gray, text-sm
│ │
│ [头像] 作者 ❤ 100 │ ← flex, justify-between
└─────────────────────────┘
text
底部信息区域使用 slot 插槽,方便后续扩展不同的展示方式。
Props 定义
const props = defineProps({
image: { type: String, default: '' },
width: { type: String, default: '360rpx' },
height: { type: String, default: '200rpx' },
title: { type: String, default: '' },
subtitle: { type: String, default: '' },
tagText: { type: String, default: '' },
tagClass: { type: String, default: '' },
tagStyle: { type: [String, Object], default: () => ({}) }
})
typescript
组件实现
完整结构
<template>
<view class="rounded-3 overflow-hidden shadow" :style="{ width }">
<!-- 图片区域 -->
<view class="relative">
<view
class="bg-cover bg-center"
:style="{ height, backgroundImage: `url(${image})` }"
/>
<!-- 右上角标签 -->
<view
v-if="tagText"
class="absolute right-2 top-2 px-2 py-1 rounded text-white text-xs scale-80"
:class="tagClass"
:style="tagStyle"
>
{{ tagText }}
</view>
</view>
<!-- 文字区域 -->
<view class="p-2 flex flex-col">
<text v-if="title" class="font-bold text-xl line-clamp-1">{{ title }}</text>
<text v-if="subtitle" class="text-gray-400 text-sm py-1 line-clamp-2">
{{ subtitle }}
</text>
<!-- 底部插槽:作者、点赞等 -->
<slot>
<view class="flex justify-between items-center py-2">
<view class="flex items-center">
<up-avatar :src="avatar" size="20" />
<text class="ml-2 text-gray-400 text-sm">{{ author }}</text>
</view>
<view class="flex items-center">
<up-icon name="heart" size="22" class="mr-2" />
<text class="text-gray-400 text-sm">100</text>
</view>
</view>
</slot>
</view>
</view>
</template>
vue
样式要点
| 元素 | class | 说明 |
|---|---|---|
| 卡片圆角 | rounded-3 | 与设计稿统一 |
| 阴影 | shadow | 浅色投影增加层次感 |
| 标签定位 | absolute right-2 top-2 | 右上角偏移 |
| 标签缩放 | scale-80 | 比正常字号小一点 |
| 标题省略 | line-clamp-1 | 单行省略 |
| 子标题省略 | line-clamp-2 | 两行省略 |
"大家都在学"区域实现
使用 grid 布局实现四宫格:
<template>
<vp-card title="大家都在学" wrapClass="p-x-2 p-y-4">
<view class="grid grid-cols-2 gap-3">
<vp-course-item
v-for="(item, index) in courseList"
:key="index"
:image="item.image"
:title="item.title"
tagText="热门"
tagClass="bg-orange-500"
>
<view class="flex justify-between items-center py-2">
<view class="flex items-center">
<up-avatar :src="item.avatar" size="20" />
<text class="ml-2 text-gray-400 text-sm">{{ item.author }}</text>
</view>
<view class="flex items-center">
<up-icon name="heart" size="22" class="mr-2" />
<text class="text-gray-400 text-sm">{{ item.likes }}</text>
</view>
</view>
</vp-course-item>
</view>
</vp-card>
</template>
vue
首页背景色
首页整体需要一个非纯白的浅色背景:
<template>
<view style="background-color: #f5f5f5">
<!-- 页面内容 -->
</view>
</template>
vue
TypeScript 类型导入注意
在 HBuilderX 项目中使用 TypeScript 时,如果提示 Vue 模块未导出 PropType 或 StyleValue,需要使用 import type 方式导入:
// 错误
import { PropType, StyleValue } from 'vue'
// 正确
import type { PropType, StyleValue } from 'vue'
typescript
首页样式总结
首页开发涉及的核心技能点:
- 组件拆分:识别可复用区域,封装为基础组件
- Props 设计:通过 props 控制组件的差异化展示
- Slot 使用:为可变区域预留插槽
- CSS 框架:熟练使用 UnoCSS/TailwindCSS 的原子化 class
- 小程序特性:理解小程序中 z-index、样式优先级等差异
- 调试策略:对照设计稿逐步调整,耐心打磨细节
↑