移动端h5主题适配方案(包括图片和颜色)

20 阅读3分钟

真实落地方案,我们落地的方案颜色使用的是css变量方式这个方案,图片就使用的下面那一种,使用起来目前还没发现什么问题。方案如下:

颜色适配

css变量方式

动态改变html上绑定的变量

1. 配置全局变量主题颜色

:root[data-theme="blue"] {
    --color-bg: rgba(11, 36, 77, 1);
    --color-border: rgba(255, 255, 255, 0.08);
    --color-text: rgba(255, 255, 255, 0.9);
    --color-share: rgba(255, 140, 0, 1);
}

:root[data-theme="white"] {
    --color-bg: rgba(255, 255, 255, 1);
    --color-border: rgba(0, 0, 0, 0.05);
    --color-text: rgba(51, 51, 51, 1);
    --color-share: rgba(0, 140, 0, 1);
}

:root[data-theme="black"] {
    --color-bg: rgba(31, 31, 31, 1);
    --color-border: rgba(255, 255, 255, 0.05);
    --color-text: rgba(255, 255, 255, 0.9);
    --color-share: rgba(180, 10, 0, 1);
}

2. 页面初次加载和主题切换

主题的str存为响应式数据,便于后续拓展

import { defineStore } from "pinia";
import { ref } from "vue";

export const useThemeStore = defineStore('theme', () => {
    const theme = ref(localStorage.getItem('theme') || 'blue');
    function initTheme() {
        const themeStr: string = localStorage.getItem('theme') || 'blue';
        // 初始化主题变量
        document.documentElement.setAttribute('data-theme', themeStr);
    }
    function switchTheme(theme: string) {
        // 切换主题变量
        document.documentElement.setAttribute('data-theme', theme);
        // 保存主题到本地存储
        localStorage.setItem('theme', theme);
    }
    return { theme, initTheme, switchTheme }
})

3. 模板中使用主题

依旧是两种方案,方案一使用动态样式的方法,方案二使用动态类的方法

方案一

 <div :style="{ color: 'var(--color-share)' }">测试文字二,模板中使用主题色</div>

方案二

 <div class="data" :class="handleColor(iten.change_pct)">{{
                        formatNumberToPercentage(iten.change_pct) }}</div>
const handleColor = (value: number | undefined | null) => {
   const num = value ?? 0
   if (num > 0) {
      return "redColor";
   } else if (num < 0) {
      return "greenColor";
   } else {
      return "whiteColor";
   }
};
.redColor {
   color: var(--color-share1) !important;
}

.greenColor {
   color: var(--color-share2) !important;
}

.whiteColor {
   color: var(--color-share3) !important;
}

4. 缺点

在主题切换的时候变化内容较大,可能会出现短暂白屏时间

css预处理器方案

核心要点就是一开始就要将主题样式全部设置好,比如我这种3个主题就要编译出来3套css

方案各有优缺点,这种方案自己研究下

1. 具体实现

通过预处理器变量和mixin,在构建时生成多套主题CSS文件

2.缺点

  1. 可能首屏白屏时间过长
  2. 团队之间要规范好,还有各种混入要提前处理好
  3. 感觉这个有点麻烦,还是推荐方案一

图片适配

主题的适配还有图片相关的适配,这种应该如何处理

这种一般比较简单,看图片是放服务器还是放各大厂商上面,比如阿里oss,不管放哪里,思路都是一样的

  1. 创建3个文件夹,blue/white/black,分别将不同主题的图片传到不同文件夹下面
  2. 从store中拿到相对应的主题字符串,然后根据这个字符串来拼接对应的图片地址
  3. 相对应的获取图片代码大概类似下面,我写的比较简单,可以适当拓展
export function imgUrl(iconName: string) {
    const useThemeInfo = useThemeStore()
    const { theme } = storeToRefs(useThemeInfo)
    return `${href}/${theme}/${iconName}`;
}

这个函数直接放到模板中,因为里面有响应式属性,所以主题切换的时候是响应式的,但是有一个注意点

场景:表头有2块区域对应6个卡片,对应不同的背景色,然后循环设置背景色,我们存到数组中然后循环设置背景色,这种情况会丢失响应式,这种记得要特殊处理,使用computed包一层

  <div class="card-item" v-for="(cardItem, idx) in Data[item]"
                        :key="cardItem.id"
                        :style="{ backgroundImage: `url(${rankingIconMap[index][idx]})` }"></div>
const rankingIconMap = computed(() => [
    [imgUrl('pic_b_55a@3x.png'), imgUrl('pic_b_55b@3x.png'), imgUrl('pic_b_55c@3x.png')],
    [imgUrl('pic_b_54a@3x.png'), imgUrl('pic_b_54b@3x.png'), imgUrl('pic_b_54c@3x.png')]
])