uniapp换肤最佳实践

前言

换肤是对应用的主题进行切换。需要在不修改代码和结构的前提下,通过动态切换一套样式规则,来改变应用的整体视觉外观,从而为用户提供不同的视觉体验。

而在uniapp中实现换肤,就需要考虑不同平台的实现,本文将介绍一种比较通用的最佳解决方案。

主要亮点有:

  1. 主题色后台进行不同平台配置,通过接口获取
  2. 无需使用类名切换,直接使用变量
  3. 可以利用主题色,衍生出颜色色阶,无需额外定义

在线预览:

接下来话不多说,开始实践部分。

1. 整体实现方式

整体流程梳理:

  1. 后台定义主题色等颜色
  2. 接口请求主题色,转换成CSS变量。注意: 主题色需要转换成rgb,用于衍生出其他颜色色阶, 如--mainColor:#FF4757, --mainRgbColor:255,71,87
  3. 页面根元素绑定,style="--mainColor:#FF4757"
  4. 页面使用,color: var(--mainColor);background: rgba(--mainRgbColor, 0.5)

说明:通用标签的背景色是根据主题色衍生出来的,这里就需要转换成rgb的形式进行使用。

2. 案例说明

接下来我们使用uniapp+vue3+pinia进行案例演示,包括编译后的app、h5、小程序进行实践。

我们整体代码实现思路是:通过pinia进行整体的设置和存储,接口获取时,我们需要额外计算出主题色的rgb

2.1 pinia设置和存储

我们使用pinia进行统一管理我们的换肤颜色。

ini 复制代码
import { defineStore } from 'pinia';
import { ref } from 'vue';

export const useThemeStore = defineStore(
  'theme',
  () => {
    const themeInfo = ref(`--bg:#F8F8F8;--mainColor:#FF4757;--mainRgbColor:255,71,87;--subColor:#FFECED;--priceColor:#FF3838;`);

    const setTheme = (val: string) => {
      themeInfo.value = val;
    };

    const resetTheme = () => {
      themeInfo.value = '';
    };

    return {
      themeInfo,
      setTheme,
      resetTheme,
    };
  },
  {
    persist: true
  }
);

2.2 接口请求

我们需要请求自己平台的主题色,进行设置存储。需要将主题色进行转换成rgb形式,方便后续使用。

注意:如果在less中,我们可以使用fade进行rgba的操作,问题是fade函数不支持变量形式,仅仅只能用fade(#FFFFFF,0.2)。 如果使用变量,我们只能转换成rgb的字符,利用rgba实现

js 复制代码
import { useThemeStore } from '@/store';

const hexToRgbStr = (hex: string): string => {
  try {
    // 扩展 3 位格式到 6 位
    const shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
    hex = hex.replace(shorthandRegex, (m, r, g, b) => {
      return r + r + g + g + b + b;
    });
    // 解析 6 位 HEX 格式
    const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
    if (!result) return ''
    return `${parseInt(result[1], 16)},${parseInt(result[2], 16)},${parseInt(result[3], 16)}`;

  } catch (error) {
    return ''
  }
}


const handleChange = () => {
  const mainColor = '#FF4757'
  const mainRgbColor = hexToRgbStr(mainColor)
  const colorStr = `--mainColor:${mainColor};--mainRgbColor:${mainRgbColor};--subColor:#FFECED;--priceColor:#FF3838;`
  useThemeStore().setTheme(colorStr)
}

2.3 页面使用

页面使用需要在页面的根元素绑定style,这样就可以在css中使用颜色变量了。

js 复制代码
<div :style="useThemeStore().themeInfo"></div>
css 复制代码
.main {
  color: var(--mainColor);
  background: rgba(var(--mainRgbColor),0.3);
}

2.4 一点开发优化

我们在使用css的时候,会一直使用var,我们希望用更简单的方式进行书写。例如:

scss 复制代码
.main {
  color: $color-theme;
  background: rgba($color-rgb-theme,0.3);
}

这种写法让我们的开发更加舒服,那么怎么去实现这样呢?也很简单,我们只需要定义一个通用的skin.scss,将这些变量定义进去,全局引入即可使用。

下面介绍两个引入方案:

2.4.1 使用vite全局引入

方案一:

  1. 定义skin.scss,定义变量
  2. 如果直接引入到页面会报错,我们直接在vite.config.ts中声明引入
  3. 页面直接使用

如果我们不想使用var()这种形式,需要在vite.config.ts中声明提前加载的css:

ts 复制代码
css: {
    preprocessorOptions: {
      scss: {
        additionalData: `@import "@/styles/skin.scss";` // 全局注入
      }
    }
  }

skin.scss:

scss 复制代码
$color-bg: var(--bg);
$color-theme: var(--mainColor);
$color-rgb-theme: var(--mainRgbColor);
$color-theme-d: var(--subColor);
$color-price: var(--priceColor);

这样就可以使用$形式,可以去除var这种写法。

css 复制代码
.main {
  color: $color-theme;
}

2.4.2 使用uni.scss引入

方案二:

我们需要使用到uni.scss,它是一个特殊文件,在代码中无需 import 这个文件即可在scss代码中使用这里的样式变量。uni-app的编译器在webpack配置中特殊处理了这个uni.scss,使得每个scss文件都被注入这个uni.scss,达到全局可用的效果。

我们在此只需要将skin.scss定义的css变量移动到uni.scss中定义即可,也无需在vite中声明。

scss 复制代码
$color-bg: var(--bg);
$color-theme: var(--mainColor);
$color-rgb-theme: var(--mainRgbColor);
$color-theme-d: var(--subColor);
$color-price: var(--priceColor);

3. 效果展示

4. 总结

最后总结一下,主要就是利用CSS变量和RGB转换,实现换肤效果,并且在书写中,优化了一点开发体验。

如有错误,请指正O^O!

相关推荐
陪我一起学编程22 分钟前
创建Vue项目的不同方式及项目规范化配置
前端·javascript·vue.js·git·elementui·axios·企业规范
LinXunFeng1 小时前
Flutter - 详情页初始锚点与优化
前端·flutter·开源
GISer_Jing1 小时前
Vue Teleport 原理解析与React Portal、 Fragment 组件
前端·vue.js·react.js
Summer不秃1 小时前
uniapp 手写签名组件开发全攻略
前端·javascript·vue.js·微信小程序·小程序·html
coderklaus1 小时前
Base64编码详解
前端·javascript
NobodyDJ2 小时前
Vue3 响应式大对比:ref vs reactive,到底该怎么选?
前端·vue.js·面试
xianxin_2 小时前
CSS Visibility(可见性)
前端
朱程2 小时前
写给自己的 LangChain 开发教程(二):格式化数据 & 提取 & 分类
前端·人工智能
小喷友2 小时前
第5章 高级UI与动画
前端·app·harmonyos
笃行3502 小时前
【实用部署教程】olmOCR智能PDF文本提取系统:从安装到可视化界面实现
前端