Taro样式重构记录

前言

公司的商城小程序一直是开发几个周然后就停几个周。并且经由了多人开发,每个页面的样式也不统一。并且由于UI同学在figma上的UI图也不统一(比如有的间距是12px,有的间距是16px,但都是同样的卡片)。因此团队决定重构样式。

如何重构

主要是定义一系列的css变量。因为本项目没有使用任何css工具

css 复制代码
:root,
page {
  color: #333333;
  --nutui-color-primary: #ffcf14;
  /** 主要内容用色,常用语常规标题内容、细文浏览、常规按钮文字以及图表引导。*/
  --nutui-gray-7: #333333;
  /** 次要文字色,用于次级标题、属性标示、非主要信息引导等。*/
  --nutui-black-10: #666666;
  /** 不可操作内容色,用于预置内容、无效内容、特殊不可点击按钮、组件边框线等。*/
  --nutui-gray-6: #cccccc;
  /** 页面基底色,用于卡片式页面的兜底,永远置于页面最底层。*/
  --nutui-gray-5: #f7f8fa;
  /** 卡片内嵌背景色,用于卡片内部的信息包裹,感知较弱。*/
  --nutui-gray-4: #f7f8fc;
  /** 卡片背景色*/
  --nutui-black-3: #ffffff;
  /** 页面全局蒙层,用于弹出层、弹窗、新功能引导出现的整页遮罩*/
  --nutui-gray-3: rgba(0, 0, 0, 0.7);
  /** 局部蒙层,用于非整页遮罩*/
  --nutui-gray-2: rgba(0, 0, 0, 0.4);
  /** 间隔线/容错线,用于结构或信息分割*/
  --nutui-black-2: rgba(0, 0, 0, 0.08);
  /** 图片容错蒙层 */
  --nutui-gray-1: rgba(0, 0, 0, 0.02);

  /** 主题色 */
  --tx-bg: #ffcf14;
  /** 次主色 */
  --tx-bg-secondary: #ae7466;
  /** 浅主色 */
  --tx-bg-light: #fff8e5;
  /* 主文本浅颜色 */
  --tx-text-primary-light: #E79600;
  /** 主文本颜色 */
  --tx-text: #333333;
  /** 常规文本颜色 */
  --tx-text-normal: #666666;
  /** 次要文本颜色 */
  --tx-text-secondary: #999999;
  /** 不可操作内容颜色 */
  --tx-text-disabled: #cccccc;
  /** 页面背景色 */
  --tx-bg-page: #f7f8fa;
  /** 卡片背景色 */
  --tx-bg-card: #ffffff;
  /** 线条颜色 */
  --tx-border: #eeeeee;
  /** 价格红色 */
  --tx-text-price: #ff4d4f;

  /** 主/次按钮高度 */
  --tx-button-height: 88rpx;
  /** 主/次按钮字号 */
  --tx-button-font-size: 32rpx;
  /** 主/次按钮x内边距 */
  --tx-button-padding-x: 64rpx;
  /** 主/次按钮高度-小 */
  --tx-button-height-small: 66rpx;
  /** 主/次按钮字号-小 */
  --tx-button-font-size-small: 28rpx;
  /** 主/次按钮x内边距-小 */
  --tx-button-padding-x-small: 40rpx;
  /** 主/次按钮高度-极小 */
  --tx-button-height-tiny: 48rpx;
  /** 主/次按钮字号-极小 */
  --tx-button-font-size-tiny: 24rpx;
  /** 主/次按钮x内边距-极小 */
  --tx-button-padding-x-tiny: 24rpx;

  /** 按钮圆角 */
  --tx-button-border-radius: 100rpx;
  /** 幽灵按钮高度 */
  --tx-ghost-button-height: 64rpx;
  /** 幽灵按钮字号 */
  --tx-ghost-button-font-size: 28rpx;
  /** 极小间距 */
  --tx-tiny-spacing: 8rpx;
  /** 小间距 */
  --tx-small-spacing: 16rpx;
  /** 中间距 */
  --tx-medium-spacing: 24rpx;
  /** 标准间距 */
  --tx-standard-spacing: 32rpx;
  /** 大间距 */
  --tx-large-spacing: 48rpx;

  /** 卡片圆角 */
  --tx-card-border-radius: 16rpx;
  /** 标签圆角 */
  --tx-label-border-radius: 4rpx;
  /** 大标签圆角 */
  --tx-large-label-border-radius: 16rpx;
  /** 弹窗圆角 */
  --tx-popup-border-radius: 24rpx;
  /** 极大标题字号 */
  --tx-xlarge-title-font-size: 48rpx;
  /** 大标题字号 */
  --tx-large-title-font-size: 40rpx;
  /** 标准行高 */
  --tx-standard-line-height: 1.4;
  /** 小字行高 */
  --tx-small-line-height: 1.2;
  /** 模块标题字号 */
  --tx-module-title-font-size: 32rpx;
  /** 商品主标题字号 */
  --tx-product-title-font-size: 28rpx;
  /** 商品副文本字号 */
  --tx-product-subtitle-font-size: 24rpx;
  /** 极小标签字号 */
  --tx-tiny-label-font-size: 20rpx;
  /** 价格整数部分字号 */
  --tx-price-integer-font-size: 36rpx;
  /** 价格小数部分字号 */
  --tx-price-decimal-font-size: 24rpx;
  /** 积分数字小字号 */
  --tx-code-font-size: 60rpx;
  /** 积分数字小字号行高 */
  --tx-code-line-height: 60rpx;
  /** 积分数字大字号 */
  --tx-code-font-size-large: 72rpx;
  /** 积分数字大字号行高 */
  --tx-code-line-height-large: 72rpx;

  color: var(--tx-text-normal);
  font-size: var(--tx-product-title-font-size);
  line-height: var(--tx-standard-line-height);
}

/** @description 主题颜色 */
.bg-theme {
  background-color: var(--tx-bg);
}

.bg-sub {
  background-color: var(--tx-bg-light);
}

.bg-page {
  background-color: var(--tx-bg-page);
}

.bg-card {
  background-color: var(--tx-bg-card);
}

/** @description 线条颜色 */
.border-color {
  border-color: var(--tx-border);
}

/** @description 文本颜色 */
.text-main {
  color: var(--tx-text);
}

.text-normal {
  color: var(--tx-text-normal);
}

.text-secondary {
  color: var(--tx-text-secondary);
}

.text-disabled {
  color: var(--tx-text-disabled);
}

.text-money {
  color: var(--tx-text-price);
}

/** @description 间距 */
.mt {
  margin-top: var(--tx-tiny-spacing);
}

.mb {
  margin-bottom: var(--tx-tiny-spacing);
}

.ml {
  margin-left: var(--tx-tiny-spacing);
}

.mr {
  margin-right: var(--tx-tiny-spacing);
}

.mx {
  margin-left: var(--tx-tiny-spacing);
  margin-right: var(--tx-tiny-spacing);
}

.my {
  margin-top: var(--tx-tiny-spacing);
  margin-bottom: var(--tx-tiny-spacing);
}

.m {
  margin: var(--tx-tiny-spacing);
}

.mt-2 {
  margin-top: var(--tx-small-spacing);
}

.mb-2 {
  margin-bottom: var(--tx-small-spacing);
}

.ml-2 {
  margin-left: var(--tx-small-spacing);
}

.mr-2 {
  margin-right: var(--tx-small-spacing);
}

.mx-2 {
  margin-left: var(--tx-small-spacing);
  margin-right: var(--tx-small-spacing);
}

.my-2 {
  margin-top: var(--tx-small-spacing);
  margin-bottom: var(--tx-small-spacing);
}

.m-2 {
  margin: var(--tx-small-spacing);
}

.m-3 {
  margin: var(--tx-medium-spacing);
}

/* 中间距 */
.mt-3 {
  margin-top: var(--tx-medium-spacing);
}

.mb-3 {
  margin-bottom: var(--tx-medium-spacing);
}

.ml-3 {
  margin-left: var(--tx-medium-spacing);
}

.mr-3 {
  margin-right: var(--tx-medium-spacing);
}

.mx-3 {
  margin-left: var(--tx-medium-spacing);
  margin-right: var(--tx-medium-spacing);
}

.my-3 {
  margin-top: var(--tx-medium-spacing);
  margin-bottom: var(--tx-medium-spacing);
}

/* 标准间距 */
.mt-4 {
  margin-top: var(--tx-standard-spacing);
}

.mb-4 {
  margin-bottom: var(--tx-standard-spacing);
}

.ml-4 {
  margin-left: var(--tx-standard-spacing);
}

.mr-4 {
  margin-right: var(--tx-standard-spacing);
}

.mx-4 {
  margin-left: var(--tx-standard-spacing);
  margin-right: var(--tx-standard-spacing);
}

.my-4 {
  margin-top: var(--tx-standard-spacing);
  margin-bottom: var(--tx-standard-spacing);
}

.m-4 {
  margin: var(--tx-standard-spacing);
}

/* 大间距 */
.mt-big {
  margin-top: var(--tx-large-spacing);
}

.mb-big {
  margin-bottom: var(--tx-large-spacing);
}

.ml-big {
  margin-left: var(--tx-large-spacing);
}

.mr-big {
  margin-right: var(--tx-large-spacing);
}

.mx-big {
  margin-left: var(--tx-large-spacing);
  margin-right: var(--tx-large-spacing);
}

.my-big {
  margin-top: var(--tx-large-spacing);
  margin-bottom: var(--tx-large-spacing);
}

.m-big {
  margin: var(--tx-large-spacing);
}

.pt-tiny {
  padding-top: var(--tx-tiny-spacing);
}
.pb-tiny {
  padding-bottom: var(--tx-tiny-spacing);
}
.pl-tiny {
  padding-left: var(--tx-tiny-spacing);
}
.pr-tiny {
  padding-right: var(--tx-tiny-spacing);
}
.px-tiny {
  padding-left: var(--tx-tiny-spacing);
  padding-right: var(--tx-tiny-spacing);
}
.py-tiny {
  padding-top: var(--tx-tiny-spacing);
  padding-bottom: var(--tx-tiny-spacing);
}
.p-tiny {
  padding: var(--tx-tiny-spacing);
}

.pt-small {
  padding-top: var(--tx-small-spacing);
}
.pb-small {
  padding-bottom: var(--tx-small-spacing);
}
.pl-small {
  padding-left: var(--tx-small-spacing);
}
.pr-small {
  padding-right: var(--tx-small-spacing);
}
.px-small {
  padding-left: var(--tx-small-spacing);
  padding-right: var(--tx-small-spacing);
}
.py-small {
  padding-top: var(--tx-small-spacing);
  padding-bottom: var(--tx-small-spacing);
}
.p-small {
  padding: var(--tx-small-spacing);
}

.pt-medium {
  padding-top: var(--tx-medium-spacing);
}
.pb-medium {
  padding-bottom: var(--tx-medium-spacing);
}
.pl-medium {
  padding-left: var(--tx-medium-spacing);
}
.pr-medium {
  padding-right: var(--tx-medium-spacing);
}
.px-medium {
  padding-left: var(--tx-medium-spacing);
  padding-right: var(--tx-medium-spacing);
}
.py-medium {
  padding-top: var(--tx-medium-spacing);
  padding-bottom: var(--tx-medium-spacing);
}
.p-medium {
  padding: var(--tx-medium-spacing);
}

.pt-standard {
  padding-top: var(--tx-standard-spacing);
}
.pb-standard {
  padding-bottom: var(--tx-standard-spacing);
}
.pl-standard {
  padding-left: var(--tx-standard-spacing);
}
.pr-standard {
  padding-right: var(--tx-standard-spacing);
}
.px-standard {
  padding-left: var(--tx-standard-spacing);
  padding-right: var(--tx-standard-spacing);
}
.py-standard {
  padding-top: var(--tx-standard-spacing);
  padding-bottom: var(--tx-standard-spacing);
}
.p-standard {
  padding: var(--tx-standard-spacing);
}

.pt-large {
  padding-top: var(--tx-large-spacing);
}
.pb-large {
  padding-bottom: var(--tx-large-spacing);
}
.pl-large {
  padding-left: var(--tx-large-spacing);
}
.pr-large {
  padding-right: var(--tx-large-spacing);
}
.px-large {
  padding-left: var(--tx-large-spacing);
  padding-right: var(--tx-large-spacing);
}
.py-large {
  padding-top: var(--tx-large-spacing);
  padding-bottom: var(--tx-large-spacing);
}
.p-large {
  padding: var(--tx-large-spacing);
}

.p-card {
  padding: var(--tx-medium-spacing);
}

.p-page {
  margin: var(--tx-standard-spacing);
}

.ml-big {
  margin-left: var(--tx-large-spacing);
}

.mr-big {
  margin-right: var(--tx-large-spacing);
}

.mt-big {
  margin-top: var(--tx-large-spacing);
}

.mb-big {
  margin-bottom: var(--tx-large-spacing);
}

.mx-big {
  margin-left: var(--tx-large-spacing);
  margin-right: var(--tx-large-spacing);
}

.my-big {
  margin-top: var(--tx-large-spacing);
  margin-bottom: var(--tx-large-spacing);
}

/** @description 圆角 */
.radius-card {
  border-radius: var(--tx-card-border-radius);
}

.radius-label {
  border-radius: var(--tx-label-border-radius);
}

.radius-label-big {
  border-radius: var(--tx-large-label-border-radius);
}

.radius-modal {
  border-radius: var(--tx-popup-border-radius);
}

/** @description 字体大小 */
.text-h1 {
  font-size: var(--tx-large-title-font-size);
  line-height: var(--tx-standard-line-height);
  font-weight: 500;
}

.text-h2 {
  font-size: var(--tx-module-title-font-size);
  line-height: var(--tx-standard-line-height);
  font-weight: 500;
}

.text-title {
  font-size: var(--tx-product-title-font-size);
  line-height: var(--tx-standard-line-height);
  font-weight: 400;
}

.text-tips {
  font-size: var(--tx-product-subtitle-font-size);
  line-height: var(--tx-standard-line-height);
  font-weight: 400;
}

.text-mini {
  font-size: var(--tx-tiny-label-font-size);
  line-height: var(--tx-small-line-height);
  font-weight: 400;
}

.text-price {
  font-size: var(--tx-price-integer-font-size);
  line-height: var(--tx-small-line-height);
  font-weight: 600;
}

.text-price-sub {
  font-size: var(--tx-price-decimal-font-size);
  line-height: var(--tx-small-line-height);
  font-weight: 600;
}

.text-code-number {
  font-size: var(--tx-code-font-size);
  line-height: var(--tx-code-line-height-large);
  font-weight: 500;
}

.text-code-number-large {
  font-size: var(--tx-code-font-size-large);
  line-height: var(--tx-code-line-height);
  font-weight: bold;
}

.gap {
  gap: var(--tx-standard-spacing);
}

.gap-block {
  gap: var(--tx-large-spacing);
}

.gap-card {
  gap: var(--tx-small-spacing);
}

.gap-medium {
  gap: var(--tx-medium-spacing);
}

.gap-tiny {
  gap: var(--tx-tiny-spacing);
}

比如规定好,大按钮、小按钮、主要文本色、次要文本色、页面间距、卡片间距等等。

如何在把原来的替换掉统一起来。

像按钮这种,就封一个组件,根据props去生成样式

tsx 复制代码
import { classNames } from '@/utils/Tool';
import { View } from '@tarojs/components';
import Taro from '@tarojs/taro';
import './index.scss';

export interface ITXButtonProps {
  children?: React.ReactNode;
  /** @param 是否占据整行 */
  block?: boolean;
  className?: string;
  /** @param 是否禁用 */
  disabled?: boolean;
  /** @param 禁用时的提示文本 */
  disabledText?: string;
  /** @param 点击事件 */
  onClick?: () => void;
  /** @param 是否为大按钮 */
  large?: boolean;
  /** @param 是否为小按钮 */
  small?: boolean;
  /** @param 是否为极小按钮 */
  tiny?: boolean;
  /** @param 是否为主要按钮 */
  theme?: boolean;
  /** @param 是否为主要按钮-浅色 */
  themeLight?: boolean;
}

export const TXButton = function TXButton_(props: ITXButtonProps) {
  return (
    <View
      className={classNames({
        'tx-button': true,
        'tx-button-block': props.block,
        small: props.small,
        tiny: props.tiny,
        large: props.large,
        disabled: props.disabled,
        theme: props.theme,
        themeLight: props.themeLight,
        [props.className || '']: true,
      })}
      onClick={() => {
        if (props.disabled) {
          if (props.disabledText) {
            Taro.showToast({
              title: props.disabledText,
              icon: 'none',
              duration: 700,
            });
          }
          return;
        }
        props.onClick?.();
      }}
    >
      {props.children}
    </View>
  );
};
css 复制代码
.tx-button {
  --bg: var(--tx-bg-page);
  --color: var(--tx-text);
  --border-radius: var(--tx-button-border-radius);
  --height: var(--tx-button-height-small);
  --font-size: var(--tx-button-font-size-small);
  --padding-x: var(--tx-button-padding-x-small);
  --font-weight: 400;

  background-color: var(--bg);
  color: var(--color);
  border-radius: var(--border-radius);
  height: var(--height);
  font-size: var(--font-size);
  font-weight: var(--font-weight);
  padding: 0 var(--padding-x);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  box-sizing: border-box;

  &.tx-button-block {
    display: flex;
  }

  &.theme {
    --bg: var(--tx-bg);
    --color: var(--tx-text);
  }

  &.themeLight {
    --color: var(--tx-text-primary-light);
    --bg: var(--tx-bg-light);
  }

  &.large {
    --height: var(--tx-button-height);
    --font-size: var(--tx-button-font-size);
    --padding-x: var(--tx-button-padding-x);
    --font-weight: 700;
  }

  &.small {
    --height: var(--tx-button-height-small);
    --font-size: var(--tx-button-font-size-small);
    --padding-x: var(--tx-button-padding-x-small);
  }

  &.tiny {
    --height: var(--tx-button-height-tiny);
    --font-size: var(--tx-button-font-size-tiny);
    --padding-x: var(--tx-button-padding-x-tiny);
  }

  &.disabled {
    --bg: var(--tx-border);
    --color: var(--tx-text-secondary);
  }
}

.nut-popup-bottom.nut-popup-round {
  border-radius: var(--tx-popup-border-radius) var(--tx-popup-border-radius) 0 0 !important;
}

在使用时

tsx 复制代码
<TXButton
  large
  theme
  block
  onClick={() => {
    if (computed.loading) return;
    logic.onSave();
  }}
>
  保存地址
</TXButton>
相关推荐
恋猫de小郭2 小时前
Google 开源大模型 Gemma4 怎么选,本地跑的话需要什么条件?
前端·人工智能·ai编程
文心快码BaiduComate2 小时前
Comate搭载GLM-5.1:长程8H,对齐Opus 4.6
前端·后端·架构
熊猫钓鱼>_>2 小时前
AI驱动的Web应用智能化:WebMCP、WebSkills与WebAgent的融合实践
前端·人工智能·ai·skill·webagent·webmcp·webskills
毛骗导演3 小时前
OpenClaw Pi Agent 深度解析:嵌入式 Agent 运行时的架构设计与实现
前端·架构
twl3 小时前
从 RAG 到可持续演化的知识库:llm-wiki 介绍
前端
傻小胖3 小时前
Object.defineProperty() 完整指南
开发语言·前端·javascript
里欧跑得慢3 小时前
Flutter 导航路由:构建流畅的应用导航体验
前端·css·flutter·web
@二进制3 小时前
vue3+vant4+ts出现页面空白?甚至在App.vue的<template></template>中随便输入都无法显示?
前端·vue.js·typescript