文章目录
- 前言
-
- [🎯 **方案一:混合模式 (推荐)**](#🎯 方案一:混合模式 (推荐))
- [🎯 **方案二:语义化组件类**](#🎯 方案二:语义化组件类)
- [🎯 **方案三:CSS 模块化**](#🎯 方案三:CSS 模块化)
- [🎯 **方案四:BEM 命名规范**](#🎯 方案四:BEM 命名规范)
- [💡 **推荐做法**](#💡 推荐做法)
前言
记录让c4 从scss 转为 原子css unocss
🎯 方案一:混合模式 (推荐)
保留语义化的 SCSS 类名,内部使用 @apply
指令应用 UnoCSS:
让我展示如何重构为语义化的 SCSS + UnoCSS 混合模式:
js
<template>
<view class="page">
<view class="tab-bar">
<view
v-for="(tab, index) in tabList"
:key="tab.key"
class="tab-item"
:class="{ 'active': currentTab === index }"
@click="changeTab(index)"
>
<text class="tab-text">{{ tab.label }}</text>
<text class="tab-count">({{ tab.count }})</text>
</view>
</view>
<!-- 成员列表 -->
<view class="content">
<scroll-view scroll-y class="scroll-container">
<view class="member-list">
<view
v-for="member in currentMemberList"
:key="member.id"
class="member-item"
>
<view class="member-info">
<image :src="member.avatar" class="avatar" mode="aspectFill" />
<view class="info">
xxx
</view>
</view>
</view>
<view class="delete-btn" @click="deleteMember(member.id)">
删除
</view>
</view>
<!-- 空状态 -->
<view v-if="currentMemberList.length === 0" class="empty-state">
<image src="/static/images/mine/no_list.webp" class="empty-icon" mode="aspectFit" />
<text class="empty-text">暂无成员</text>
</view>
</view>
</scroll-view>
</view>
</view>
</template>
<style lang="scss" scoped>
/* 使用 @apply 指令结合 UnoCSS */
.page {
@apply min-h-screen flex flex-col bg-#f7f7f7;
}
.tab-bar {
@apply bg-white flex px-32rpx border-b-2rpx border-#f5f5f5;
}
.member-item {
@apply flex items-center justify-between h-174rpx bg-white rounded-20rpx px-32rpx mb-24rpx;
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.06);
}
.add-text {
@apply text-32rpx font-600 text-white;
}
.modal-overlay {
@apply fixed top-0 left-0 right-0 bottom-0 z-1000 flex items-center justify-center p-40rpx bg-black bg-opacity-50;
}
/* 其他弹窗样式... */
</style>
🎯 方案二:语义化组件类
创建语义化的组件类,内部使用 UnoCSS:
html
<template>
<view class="member-management-page">
<view class="navigation-tabs">
<view class="tab-item" :class="{ 'is-active': currentTab === index }">
<!-- 内容 -->
</view>
</view>
<view class="member-content">
<view class="member-card">
<view class="member-basic-info">
<!-- 成员信息 -->
</view>
<view class="member-actions">
<!-- 操作按钮 -->
</view>
</view>
</view>
<view class="floating-add-section">
<view class="primary-add-button">
<!-- 添加按钮 -->
</view>
</view>
</view>
</template>
<style lang="scss" scoped>
.member-management-page {
@apply min-h-screen flex flex-col bg-#f7f7f7;
}
.navigation-tabs {
@apply bg-white flex px-32rpx border-b-2rpx border-#f5f5f5;
}
.tab-item {
@apply flex-1 py-32rpx relative flex items-center justify-center gap-8rpx cursor-pointer;
&.is-active {
&::after {
content: '';
position: absolute;
bottom: 0;
left: 50%;
transform: translateX(-50%);
width: 40rpx;
height: 4rpx;
background: #ff6600;
border-radius: 2rpx;
}
}
}
.member-content {
@apply flex-1 flex flex-col;
}
.member-card {
@apply flex items-center justify-between h-174rpx bg-white rounded-20rpx px-32rpx mb-24rpx;
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.06);
}
.member-basic-info {
@apply flex items-center flex-1 gap-24rpx mr-24rpx;
}
.member-actions {
@apply min-w-88rpx py-16rpx bg-white rounded-24rpx text-24rpx font-500 text-center flex-shrink-0 cursor-pointer transition-all-300ms;
}
.floating-add-section {
@apply fixed bottom-0 left-0 right-0 bg-white rounded-t-48rpx px-32rpx pt-24rpx pb-120rpx;
box-shadow: 0 -4rpx 20rpx rgba(0, 0, 0, 0.06);
}
.primary-add-button {
@apply w-full h-88rpx flex items-center justify-center bg-#ff6600 rounded-44rpx cursor-pointer transition-all-300ms;
box-shadow: 0 8rpx 24rpx rgba(255, 102, 0, 0.3);
&:active {
@apply opacity-90 scale-98;
}
}
</style>
🎯 方案三:CSS 模块化
使用 CSS 变量 + 语义化类名:
html
<template>
<view class="page">
<view class="tab-bar">
<view class="tab-item" :class="{ 'active': currentTab === index }">
<!-- 内容 -->
</view>
</view>
</view>
</template>
<style lang="scss" scoped>
:root {
--primary-color: #ff6600;
--text-primary: #333333;
--text-secondary: #666666;
--text-placeholder: #999999;
--bg-page: #f7f7f7;
--bg-card: #ffffff;
--border-light: #f5f5f5;
--shadow-card: 0 2rpx 8rpx rgba(0, 0, 0, 0.06);
--shadow-floating: 0 -4rpx 20rpx rgba(0, 0, 0, 0.06);
--radius-small: 20rpx;
--radius-medium: 24rpx;
--radius-large: 48rpx;
}
.page {
min-height: 100vh;
display: flex;
flex-direction: column;
background: var(--bg-page);
}
.tab-bar {
background: var(--bg-card);
display: flex;
padding: 0 32rpx;
border-bottom: 2rpx solid var(--border-light);
}
.tab-item {
flex: 1;
padding: 32rpx 0;
position: relative;
display: flex;
align-items: center;
justify-content: center;
gap: 8rpx;
cursor: pointer;
&.active::after {
content: '';
position: absolute;
bottom: 0;
left: 50%;
transform: translateX(-50%);
width: 40rpx;
height: 4rpx;
background: var(--primary-color);
border-radius: 2rpx;
}
}
.member-item {
display: flex;
align-items: center;
justify-content: space-between;
height: 174rpx;
background: var(--bg-card);
border-radius: var(--radius-small);
padding: 0 32rpx;
margin-bottom: 24rpx;
box-shadow: var(--shadow-card);
}
.add-button-wrapper {
position: fixed;
bottom: 0;
left: 0;
right: 0;
background: var(--bg-card);
border-radius: var(--radius-large) var(--radius-large) 0 0;
padding: 24rpx 32rpx 120rpx;
box-shadow: var(--shadow-floating);
}
</style>
🎯 方案四:BEM 命名规范
使用 BEM 命名约定保持语义性:
html
<template>
<view class="member-page">
<view class="member-page__tabs">
<view class="member-page__tab member-page__tab--active">
<!-- 标签内容 -->
</view>
</view>
<view class="member-page__content">
<view class="member-card">
<view class="member-card__info">
<view class="member-card__avatar"></view>
<view class="member-card__details">
<view class="member-card__name-section">
<!-- 姓名和编辑 -->
</view>
<view class="member-card__address-section">
<!-- 地址和复制 -->
</view>
</view>
</view>
<view class="member-card__actions">
<!-- 删除按钮 -->
</view>
</view>
</view>
<view class="member-page__floating-actions">
<button class="member-page__add-btn">
<!-- 添加按钮 -->
</button>
</view>
</view>
</template>
<style lang="scss" scoped>
.member-page {
@apply min-h-screen flex flex-col bg-#f7f7f7;
&__tabs {
@apply bg-white flex px-32rpx border-b-2rpx border-#f5f5f5;
}
&__tab {
@apply flex-1 py-32rpx relative flex items-center justify-center gap-8rpx cursor-pointer;
&--active::after {
content: '';
position: absolute;
bottom: 0;
left: 50%;
transform: translateX(-50%);
width: 40rpx;
height: 4rpx;
background: #ff6600;
border-radius: 2rpx;
}
}
&__content {
@apply flex-1 flex flex-col;
}
&__floating-actions {
@apply fixed bottom-0 left-0 right-0 bg-white rounded-t-48rpx px-32rpx pt-24rpx pb-120rpx;
box-shadow: 0 -4rpx 20rpx rgba(0, 0, 0, 0.06);
}
&__add-btn {
@apply w-full h-88rpx flex items-center justify-center bg-#ff6600 rounded-44rpx cursor-pointer transition-all-300ms;
box-shadow: 0 8rpx 24rpx rgba(255, 102, 0, 0.3);
&:active {
@apply opacity-90 scale-98;
}
}
}
.member-card {
@apply flex items-center justify-between h-174rpx bg-white rounded-20rpx px-32rpx mb-24rpx;
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.06);
&__info {
@apply flex items-center flex-1 gap-24rpx mr-24rpx;
}
&__avatar {
@apply w-88rpx h-88rpx rounded-20rpx flex-shrink-0;
}
&__details {
@apply flex-1;
}
&__name-section {
@apply flex items-center gap-12rpx mb-12rpx;
}
&__address-section {
@apply flex items-center gap-8rpx;
}
&__actions {
@apply min-w-88rpx py-16rpx bg-white rounded-24rpx text-24rpx font-500 text-center flex-shrink-0 cursor-pointer transition-all-300ms;
color: var(--text-placeholder);
&:active {
@apply bg-#f8f8f8 text-#333333;
}
}
}
</style>
💡 推荐做法
方案一(混合模式),因为它:
- 保持语义性: 类名清晰表达组件功能
- 利用 UnoCSS : 通过
@apply
获得原子化 CSS 的好处 - 易于维护: 样式集中管理,便于修改
- 性能优化: 结合两种方案的优势
- 团队友好: 新成员容易理解代码结构