前言
开发中常需调整组件样式(间距、颜色等),会涉及样式覆盖与 CSS 变量。本文说明如何正确修改 SmartUI 组件样式。
一、组件结构说明
SmartUI 基于 Web Component,Ray 在编译时会为每个原生组件外层生成唯一的标签名,命名规则为:{组件目录名}-{文件名}-{路径哈希},其中路径哈希是组件完整路径的 MD5 值(取前6位),用于确保不同来源的同名组件不会产生冲突。例如:
- 项目自定义组件:src/components/nav-bar/index → nav-bar-index-abc123
- npm 包组件:node_modules/@tuya-miniapp/smart-ui/dist/nav-bar/index → nav-bar-index-404ec1
所以 SmartUI 组件外层都会有一个 行内样式的标签,可视为一个普通的行内 view。
以 NavBar 为例,在 Ray 上的 DOM 结构为:
Code: Select all
<nav-bar-index-404ec1>
<!-- 组件内部内容 -->
<view class="smart-nav-bar">
...
</view>
</nav-bar-index-404ec1>要点:样式要生效,需作用到内部的 view 等节点,而非仅作用在外层组件标签上。
二、三种样式覆盖属性
除组件自带的 CSS 控制属性外,SmartUI 组件统一提供 className、customClass、customStyle 三个属性,用于样式覆盖。
2.1 className
作用位置:仅挂载在外层组件标签(如 <nav-bar-index-404ec1>)上,不直接作用到内部节点。
若只给该节点设样式(如背景色),内部看不到效果:
Code: Select all
<NavBar title="Smart UI 首页" className="myNavBar" />Code: Select all
// app.less
.myNavBar {
background-color: red; /* 无效:只作用在外层容器 */
}正确用法:在 className 对应的 class 下,写子选择器命中内部 class(如 .smart-nav-bar):
Code: Select all
// app.less
.myNavBar {
.smart-nav-bar {
background-color: red;
}
}注意:若在全局直接写 .smart-nav-bar { ... },会因选择器权重低于组件内部样式而被覆盖,但是也不推荐用 !important,建议通过上述「父 class + 子 class」或后文 CSS 变量方式覆盖。
若使用 CSS Modules,内部 class 需用 :global() 包裹,否则会被编译成带 hash 的 class,无法命中组件内部:
Code: Select all
<NavBar title="Smart UI 首页" className={styles.myNavBar} />Code: Select all
// index.module.less
.myNavBar {
:global(.smart-nav-bar) {
background-color: red;
}
}2.2 customClass
作用位置:组件内部预留的「自定义 class 位」,对应 DOM 上的 custom-class,一般挂在第一个内部根节点。传入的 class 会替换/合并到该位置。
Code: Select all
<View className={styles.container}>
<NavBar title="Smart UI 首页" customClass={styles.myNavBar} />
</View>Code: Select all
// index.module.less
.container {
.myNavBar {
background-color: red;
}
}注意:
- DOM 上仍会显示
custom-class,实际样式已由传入的 class 生效,以最终渲染效果为准。 - 注入的 class 权重低于组件自身 class,单独写
.myNavBar { background-color: red }可能被覆盖,可放在父级选择器下(如.container .myNavBar)提高权重。
若去掉外层 .container,仅用 customClass={styles.myNavBar} 且全局只写 .myNavBar,会无法覆盖:
2.3 customStyle
作用位置:一般是组件内部根元素的内联样式(不包含外层组件标签)。因小程序限制不能直接用 style 属性,故命名为 customStyle。
直接修改内部根节点样式,无需关心 class 权重:
Code: Select all
<NavBar
title="Smart UI 首页"
customStyle={{
backgroundColor: "red",
}}
/>适合快速微调单个组件的外观。
2.4 如何判断样式来源
调试时可根据选择器特征判断样式来自哪里:
| 来源 | 选择器特征 |
|---|---|
| SmartUI组件自身样式 | .c-{随机串}-{组件 class} |
| 项目内全局 less | .{组件 class}(无随机串) |
| 项目内 CSS Module 覆盖 | .{你的 class}__{随机串} .{组件 class} |
三、CSS 变量覆盖(推荐)
组件内部预留了丰富的 CSS 变量, SmartUI 是不会定义这些 CSS 变量的值的,只是预留的空引用,所以开发者可以轻松在任何位置覆盖他们,不受 class 隔离影响,推荐优先使用。
3.1 全局修改
在全局 less 或页面顶层样式中设置变量:
Code: Select all
// app.less
:root {
--nav-bar-background-color: red;
}3.2 局部修改
配合 className,在对应 class 下覆盖变量,只影响该实例:
Code: Select all
<NavBar title="Smart UI 首页" className="myNavBar" />Code: Select all
// app.less
.myNavBar {
--nav-bar-background-color: red;
}CSS Module 中同样在 className 对应的 class 下写变量即可:
Code: Select all
<NavBar title="Smart UI 首页" className={styles.myNavBar} />Code: Select all
// index.module.less
.myNavBar {
--nav-bar-background-color: red;
}3.3 配合 ConfigProvider
主题级配置可使用 ConfigProvider 的 themeVars:
Code: Select all
<ConfigProvider
themeVars={{
navBarBackgroundColor: "red",
}}
>
<NavBar title="Smart UI 首页" />
</ConfigProvider>详细用法见:ConfigProvider 组件最佳实践
SmartUI Wiki:如何去自定义修改SmartUI组件的样式