当前位置: 首页 > news >正文

【uniapp实践】主题样式配置浅色深色以及自定义

实现效果:

1.需要配置的样式

1.1 设置每个主题对应的颜色, 主题配置映射 $themes:

@/styles/themes/variables.scss

// 主题配置映射
$themes: (light: (// 基础颜色--color-primary: #2979ff,--color-success: #19be6b,--color-warning: #ff9900,--color-error: #fa3534,--color-info: #909399,// 背景色--bg-color: #ffffff,--bg-color-page: #f2f2f6,--bg-color-grey: #f7f7f7,--bg-color-card: #ffffff,// 文字颜色--text-color: #303133,--text-color-regular: #606266,--text-color-secondary: #909399,--text-color-placeholder: #c0c4cc,// 边框颜色--border-color: #e4e7ed,--border-color-light: #ebeef5,// 阴影--box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1),// uView主题映射--u-primary: #2979ff,--u-success: #19be6b,--u-warning: #ff9900,--u-error: #fa3534),dark: (--color-primary: #2b85e4,--color-success: #18b566,--color-warning: #f29100,--color-error: #d63031,--color-info: #6b7280,--bg-color: #1a1a1a,--bg-color-page: #0f0f0f,--bg-color-grey: #2d2d2d,--bg-color-card: #2d2d2d,--text-color: #e5e7eb,--text-color-regular: #d1d5db,--text-color-secondary: #9ca3af,--text-color-placeholder: #6b7280,--border-color: #374151,--border-color-light: #4b5563,--box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.6),--u-primary: #2b85e4,--u-success: #18b566,--u-warning: #f29100,--u-error: #d63031),blue: (--color-primary: #409eff,--color-success: #67c23a,--color-warning: #e6a23c,--color-error: #f56c6c,--color-info: #909399,--bg-color: #ecf5ff,--bg-color-page: #d9ecff,--bg-color-grey: #f0f7ff,--bg-color-card: #ffffff,--text-color: #303133,--text-color-regular: #606266,--text-color-secondary: #909399,--text-color-placeholder: #c0c4cc,--border-color: #b3d8ff,--border-color-light: #d9ecff,--box-shadow: 0 2px 12px 0 rgba(64, 158, 255, 0.1),--u-primary: #409eff,--u-success: #67c23a,--u-warning: #e6a23c,--u-error: #f56c6c),red: (--color-primary: #e74c3c,--color-success: #27ae60,--color-warning: #f39c12,--color-error: #c0392b,--color-info: #95a5a6,--bg-color: #fdedec,--bg-color-page: #fadbd8,--bg-color-grey: #fbefef,--bg-color-card: #ffffff,--text-color: #2c3e50,--text-color-regular: #34495e,--text-color-secondary: #7f8c8d,--text-color-placeholder: #bdc3c7,--border-color: #f5b7b1,--border-color-light: #fadbd8,--box-shadow: 0 2px 12px 0 rgba(231, 76, 60, 0.1),--u-primary: #e74c3c,--u-success: #27ae60,--u-warning: #f39c12,--u-error: #c0392b)
);

1.2 混入

@styles/mixins.scss

@import '@/styles/themes/variables.scss';// 应用主题变量
@mixin apply-theme($theme-name) {$theme: map-get($themes, $theme-name);@each $key, $value in $theme {#{$key}: #{$value};}
}// 主题混入 - 用于在scoped样式中使用主题变量
@mixin theme-property($property, $key, $important: false) {@each $theme-name, $theme-map in $themes {$value: map-get($theme-map, $key);[data-theme="#{$theme-name}"] & {@if $important {#{$property}: #{$value} !important;} @else {#{$property}: #{$value};}}}
}// 快捷混入
@mixin background-color($color, $important: false) {@include theme-property(background-color, $color, $important);
}@mixin color($color, $important: false) {@include theme-property(color, $color, $important);
}@mixin border-color($color, $important: false) {@include theme-property(border-color, $color, $important);
}@mixin fill($color, $important: false) {@include theme-property(fill, $color, $important);
}

1.2.1 应用主题变量混入:apply-theme($theme-name)

通过主题名称来应用主题的所有变量。

@mixin apply-theme($theme-name) {$theme: map-get($themes, $theme-name); //根据主题名获取对应主题的变量映射@each $key, $value in $theme { //循环遍历当前主题的所有变量#{$key}: #{$value};// 输出 "变量名: 值"(如 --color-primary: #072046)}
}

如何使用:

// 全局样式文件(非 scoped)
@import '@/styles/mixins.scss';// 给根元素注入 light 主题的所有变量
.page-container[data-theme="light"] {@include apply-theme(light); // 输出所有 light 主题的变量(--color-primary: #072046 等)
}// 注入 dark 主题的所有变量
.page-container[data-theme="dark"] {@include apply-theme(dark); // 输出所有 dark 主题的变量
}

1.2.2 主题属性混入:theme-property($property, $key, $important: false)


// 主题混入 - 用于在scoped样式中使用主题变量
@mixin theme-property($property, $key, $important: false) {@each $theme-name, $theme-map in $themes {//循环所有主题(light/dark/custom...)$value: map-get($theme-map, $key);//获取当前主题下 $key 对应的变量值(如 $key 为 --color-primary 时,light 主题值为 #072046)[data-theme="#{$theme-name}"] & {//生成 "主题标识 + 目标选择器" 的样式规则@if $important {#{$property}: #{$value} !important;} @else {#{$property}: #{$value};}}}
}

使用:

.card {// 给 .card 的 background-color 适配所有主题@include theme-property(background-color, --bg-card); // 等同于自动生成:// [data-theme="light"] .card { background-color: #ffffff; }// [data-theme="dark"] .card { background-color: #1e1e1e; }// [data-theme="custom"] .card { background-color: #fff8e1; }
}.title {// 给 .title 的 color 适配所有主题,且加 !important@include theme-property(color, --color-text, true);
}

1.2.3 快捷混入(语法糖)

// 背景色快捷混入
@mixin background-color($color, $important: false) {@include theme-property(background-color, $color, $important);
}// 文字色快捷混入
@mixin color($color, $important: false) {@include theme-property(color, $color, $important);
}// 边框色快捷混入
@mixin border-color($color, $important: false) {@include theme-property(border-color, $color, $important);
}// 填充色(如 SVG fill)快捷混入
@mixin fill($color, $important: false) {@include theme-property(fill, $color, $important);
}

简化 theme-property 的使用,避免重复写 theme-property 和 CSS 属性名,提高开发效率。

使用:
 

.card {// 等价于 @include theme-property(background-color, --bg-card);@include background-color(--bg-card); 
}.title {// 等价于 @include theme-property(color, --color-text, true);@include color(--color-text, true);
}.theme-option {// 等价于 @include theme-property(border-color, --border-color);@include border-color(--border-color);
}

1.3 主题样式入口文件,实现多样式作用于根文件。

@import '@/styles/themes/variables.scss';
@import './mixins.scss';// 为每个主题生成CSS变量
@each $theme-name, $theme-map in $themes {[data-theme="#{$theme-name}"] {@include apply-theme($theme-name);// 主题特定的全局样式background-color: var(--bg-color-page);color: var(--text-color);// 平滑过渡效果transition: background-color 0.3s ease, color 0.3s ease;}
}// 全局主题类
.theme-primary {color: var(--color-primary);
}.theme-bg {background-color: var(--bg-color);
}.theme-card {background-color: var(--bg-color-card);border-color: var(--border-color-light);
}.theme-text {color: var(--text-color);
}.theme-text-regular {color: var(--text-color-regular);
}.theme-border {border-color: var(--border-color);
}

1.4 pina实现统一管理主题配置、切换逻辑、持久化存储、以及 TabBar 样式同步

import { defineStore } from 'pinia'
import { ref, computed, watch } from 'vue'export const useThemeStore = defineStore('theme', () => {// 当前主题const currentTheme = ref('light')// 主题列表const themeList = ref([{ name: 'light', label: '浅色主题', icon: '🌞',tabBar: {backgroundColor: '#ffffff',borderStyle: 'black',color: '#999999',selectedColor: '#2979ff'}},{ name: 'dark', label: '深色主题', icon: '🌙',tabBar: {backgroundColor: '#1a1a1a',borderStyle: 'white',color: '#666666',selectedColor: '#2b85e4'}},{ name: 'blue', label: '蓝色主题', icon: '💙',tabBar: {backgroundColor: '#ecf5ff',borderStyle: 'black',color: '#909399',selectedColor: '#409eff'}},{ name: 'red', label: '红色主题', icon: '❤️',tabBar: {backgroundColor: '#fdedec',borderStyle: 'black',color: '#909399',selectedColor: '#e74c3c'}}])// 获取当前主题的 TabBar 配置const currentTabBarConfig = computed(() => {// 从主题列表中找到当前主题对应的配置const theme = themeList.value.find(t => t.name === currentTheme.value)// 找不到则返回默认主题(第一个)的 TabBar 配置(容错处理)return theme ? theme.tabBar : themeList.value[0].tabBar})// 切换主题const switchTheme = async (themeName) => {if (themeList.value.some(theme => theme.name === themeName)) {//更新当前主题状态(响应式更新,触发组件重新渲染)currentTheme.value = themeName// 应用主题到 DOM(设置 data-theme 属性)await applyThemeToDOM(themeName)// 更新 TabBar 样式(同步底部导航栏颜色)await updateTabBarStyle()// 保存主题到本地存储(持久化,下次打开APP生效)saveThemeToStorage(themeName)}}// 应用主题到 DOMconst applyThemeToDOM = (themeName) => {return new Promise((resolve) => {// 给根元素(html)添加 data-theme 属性,值为当前主题名document.documentElement.setAttribute('data-theme', themeName)resolve()})}// 更新 TabBar 样式const updateTabBarStyle = () => {return new Promise((resolve, reject) => {// 获取当前主题的 TabBar 配置const config = currentTabBarConfig.value// 方法1: 使用 uni.setTabBarStyle (小程序官方API)if (typeof uni.setTabBarStyle === 'function') {uni.setTabBarStyle({backgroundColor: config.backgroundColor,borderStyle: config.borderStyle,color: config.color,selectedColor: config.selectedColor,success: () => {console.log('TabBar 样式更新成功')resolve()},fail: (error) => {console.error('TabBar 样式更新失败:', error)reject(error)}})} else {// 方法2: 自定义 TabBar 方案updateCustomTabBar()resolve()}})}// 更新自定义 TabBarconst updateCustomTabBar = () => {// 触发自定义 TabBar 更新if (typeof getApp === 'function') {const app = getApp()if (app && app.globalData) {app.globalData.tabBarTheme = currentTabBarConfig.value}}// 发布主题更新事件uni.$emit('themeChanged', {theme: currentTheme.value,tabBarConfig: currentTabBarConfig.value})}// 保存到本地存储const saveThemeToStorage = (themeName) => {try {uni.setStorageSync('app-theme', themeName)} catch (error) {console.warn('主题存储失败:', error)}}// 初始化主题const initTheme = () => {try {// 读取本地存储的主题(优先使用用户之前选择的主题)const savedTheme = uni.getStorageSync('app-theme')if (savedTheme) {switchTheme(savedTheme)return}// 本地无存储时,适配系统主题(如手机开启深色模式则用 dark 主题)const systemInfo = uni.getSystemInfoSync()const systemTheme = systemInfo.theme === 'dark' ? 'dark' : 'light'switchTheme(systemTheme)} catch (error) {// 异常容错(读取失败/无系统主题时,默认用 light 主题)console.warn('主题初始化失败:', error)switchTheme('light')}}return {currentTheme,themeList,currentTabBarConfig,switchTheme,initTheme}
})

1.5 页面使用

<template><view class="page-container"><!-- 顶部栏 --><view class="header theme-card"><text class="title theme-text">主题切换演示</text></view><view class="content"><!-- 主题切换 --><view class="card theme-card"><text class="card-title theme-text">切换主题</text><view class="theme-selector"><view v-for="theme in themeList" :key="theme.name" class="theme-option":class="{ active: selectedThemeName === theme.name }" @click="switchThemeClick(theme)"><text class="theme-icon">{{ theme.icon }}</text><text class="theme-label">{{ theme.label }}</text></view></view></view></view></view>
</template><script setup>import {onMounted,ref} from 'vue'import {useThemeStore} from '@/store/theme.js'const {themeList,switchTheme,initTheme,currentTheme} = useThemeStore()const selectedThemeName = ref(currentTheme?.name || '')onMounted(() => {initTheme()})const switchThemeClick = (theme) => {switchTheme(theme.name)selectedThemeName.value = theme.name}
</script><style lang="scss" scoped>.page-container {min-height: 100vh;padding: 20rpx;}.header {padding: 40rpx 30rpx;border-radius: 20rpx;margin-bottom: 30rpx;text-align: center;.title {display: block;font-size: 36rpx;font-weight: bold;margin-bottom: 10rpx;}.subtitle {display: block;font-size: 28rpx;}}.content {display: flex;flex-direction: column;gap: 30rpx;}.card {padding: 30rpx;border-radius: 20rpx;border: 1rpx solid;.card-title {font-size: 32rpx;font-weight: bold;margin-bottom: 30rpx;display: block;}}.theme-selector {display: grid;grid-template-columns: 1fr 1fr;gap: 20rpx;margin-bottom: 30rpx;.theme-option {padding: 30rpx 20rpx;border-radius: 16rpx;border: 2rpx solid var(--border-color);display: flex;flex-direction: column;align-items: center;transition: all 0.3s;&.active {border-color: var(--color-primary);background-color: var(--bg-color);color: var(--text-color);}.theme-icon {font-size: 48rpx;margin-bottom: 10rpx;}.theme-label {font-size: 26rpx;transition: color 0.3s;}}}.cycle-btn {width: 100%;}
</style>

1.6 扩展

关于Sass:

  1. 变量复用可通过$定义变量,存储颜色、尺寸、字体等常用值,便于全局统一管理和修改。比如定义主题色变量后,项目中所有用到该颜色的地方只需引用变量,修改时仅改一处即可。

    scss

    $primary-color: #2979ff;
    .button {background-color: $primary-color;
    }
    
  2. 选择器与属性嵌套支持选择器嵌套,让样式层级和 HTML 结构保持一致,减少代码冗余;还支持属性嵌套,对于 font、margin 等同命名空间的属性,可简化书写。

    scss

    // 选择器嵌套
    .header {.nav {color: #333;&:hover { // & 指代父选择器.navcolor: $primary-color;}}
    }
    // 属性嵌套
    .text {font: {size: 16px;weight: bold;}
    }
    
  3. 混合器(Mixin)类似 JS 函数,可用@mixin定义可复用的样式块,还支持传参,能轻松处理兼容性样式、重复样式等场景,通过@include调用。

    scss

    @mixin border-radius($radius: 5px) {border-radius: $radius;-webkit-border-radius: $radius;
    }
    .card {@include border-radius(8px);
    }
    
  4. 样式继承@extend指令实现选择器间的样式继承,减少重复代码。若不想保留基础选择器,可改用占位符选择器%定义基础样式。

    scss

    %base-btn {padding: 10px 20px;border: none;
    }
    .btn-primary {@extend %base-btn;background-color: $primary-color;
    }
    
  5. 数学运算支持对尺寸、百分比等数值进行加减乘除运算,方便动态计算样式值,适配不同布局需求。

    scss

    $base-width: 1000px;
    .box {width: $base-width / 2;margin: 10px + 5px;
    }
    
  6. 逻辑控制与循环提供@if条件判断、@for循环、@each遍历等指令,可动态生成批量样式,比如栅格系统的列样式。

    scss

    // @for循环生成多列样式
    @for $i from 1 to 6 {.col-#{$i} {width: 100% / $i;}
    }
    
  7. 模块化导入@import导入其他 SCSS 文件,可将变量、混合器、组件样式等拆分到不同文件,实现样式的模块化管理,让项目结构更清晰。

    scss

    @import '@/styles/variables.scss';
    @import './mixins.scss';

官网:

Sass 官方网站https://sass-lang.com/

Sass 中文网https://www.sass.hk/

http://www.dtcms.com/a/605703.html

相关文章:

  • LangChain Model I/O 使用示例
  • 北京做网站设计公司网站开发主要参考文献
  • AI 十大论文精讲(三):RLHF 范式奠基 ——InstructGPT 如何让大模型 “听懂人话”
  • GPT-5.1 发布:更智能也更“人性化“的 AI 助手
  • std::bind 的简单使用
  • 中山网站seo关键词国外开源建站系统
  • [论文阅读]Friend or Foe: How LLMs‘ Safety Mind Gets Fooled by Intent Shift Attack
  • 北京出名做网站的公司怎么查网站注册信息
  • 梧州网站建设制作个人服务器网站备案
  • ppo爬坡代码及解释
  • 广东省建设厅官方网站多少钱网站logo例子
  • C语言编译器手机版 | 高效便捷的C语言编程工具
  • Vue 项目实战《尚医通》,登录模块表单校验,笔记28
  • 都江堰旅游门户网站网站设计培训哪里好
  • 重塑 Web 性能:用 Rust 与 WASM 构建“零开销”图像处理器
  • 如何实现网络与安全的深度融合
  • 探索图像处理中的九种滤波器:从模糊到锐化与边缘检测
  • Cognex VisionPro 视觉工具集成与加载机制分析笔记
  • 网站建设需要那种技术磐安网站建设
  • 日语学习-日语知识点小记-进阶-JLPT-N1阶段应用练习(11):语法 +2022年12月N1
  • HCIP—Datacom面试技术常问问题
  • transformer 在 DETR当中的应用
  • 基于MATLAB的飞机气动导数系统辨识
  • 沧州网站设计多少钱开发微信小程序需要多少钱
  • 金融科技项目管理方式在AI加持下发展方向之,需求分析精准化减少业务与技术偏差
  • 福安城乡建设与规划局网站深圳工商注册核名查询系统
  • Unity模型中人形角色的嘴巴一直开着怎么办
  • 【支承导向元件】滚动轴承及其选型计算
  • c语言编译软件Windows使用指南|选择适合开发者需求的编译工具
  • 公司网站建网linux wordpress nginx