概述
目前能实现主题切换的方式有很多,随便一搜就一大把。但是如果在项目最开始没有考虑主题切换,而后续又要新增主题切换功能。如果处理呢?这时候再加什么scss变量、什么vuex,估计看着头都有些大了吧。下面提供两个比较简单的思路。
根元素css变量挂载
直接在根元素上挂载全局css变量,在页面中使用
var(--theme-color)
变量就行
- uniapp中的 App.vue:uni中
App.vue
本身不是页面,不能编写视图元素,也就是没有<template>
# App.vue/App.uvue - 那应该怎么办呢?可以引入一个全局组件,在组件中把样式挂载上去,这样做有下面几个好处:
- 可以挂载常用组件:由于uni中不能在App.vue中挂载视图元素,对于一些经常常用的组件可以挂载在这个全局组件
g-page
上(如 confirm 确认框,popup 弹窗等等)。 - 方便页面维护:可以为所有页面配置统一的样式。
- 使用灵活:
g-page
可以挂载到任何一个地方你想要使用主题色的地方。如果不想要某个页面随主题切换。不引入这个全局组件就行。 - 使用简单:只要在页面中找到想要随主题切换的颜色,修改为css变量就行。
- 可以挂载常用组件:由于uni中不能在App.vue中挂载视图元素,对于一些经常常用的组件可以挂载在这个全局组件
全局组件封装,很简单封装,复杂主题可以再进行封装
<template>
<view
:class="['hz-page', store.appOption.theme === 'dark' ? 'theme-dark' : 'theme-light']"
:style="{
'--theme-bg-color': themeStyle.bgColor,
'--theme-bg-color-light-1': themeStyle.bgColorLight1,
'--theme-bg-white-color': themeStyle.bgWhiteColor,
'--theme-bg-color-deep': themeStyle.bgColorDeep,
'--theme-bg-book-color': themeStyle.bgColorBook,
'--theme-primary-color': themeStyle.primaryColor,
'--theme-primary-book-color': themeStyle.primaryBookColor,
'--theme-primary-color-light-1': themeStyle.primaryColorLight1,
'--theme-grey-color': themeStyle.greyColor,
'--theme-link-color': themeStyle.linkColor,
'--theme-border-color': themeStyle.borderColor,
'--theme-border-color-light-1': themeStyle.borderColorLight1,
'--theme-light-icon-color': themeStyle.lightIconColor,
'--theme-grey-icon-color': themeStyle.greyIconColor,
'--theme-icon-active-color': themeStyle.iconActiveColor,
'--theme-icon-link-color': themeStyle.iconLinkColor,
}"
>
<slot></slot>
</view>
</template>
<script setup lang="ts">
import { computed } from "vue";
import store from "@/store";
const pages = getCurrentPages();
let currentRoute = pages[pages.length - 1].route;
// console.log("当前页面路径:" + currentRoute);
const themeStyle = computed(() => {
let isDark = store.appOption.theme === "dark";
if (currentRoute === "pages/reader/index") {
// 目前产品设计逻辑阅读器主题和app主题是分开的
isDark = store.bookOption.theme === "dark";
}
return {
bgColor: isDark ? "#2A241D" : "#FEF7F1",
bgColorLight1: isDark ? "#3B352E" : "#F4EEE7",
bgColorDeep: isDark ? "#1D1710" : "#f4eee7",
bgWhiteColor: isDark ? "#38312B" : "#f1edea",
bgColorBook: isDark ? "#4c4945" : "#c0a374",
lightIconColor: isDark ? "#FEF7F1" : "#251e18",
greyIconColor: isDark ? "#a8a19a" : "#554334",
iconActiveColor: isDark ? "#EC5D57" : "#D44842",
iconLinkColor: isDark ? "#4F5C75" : "#92afe2",
primaryColor: isDark ? "#E9E3DC" : "#251e18",
primaryBookColor: isDark ? "#c9c9c9" : "#482936",
primaryColorLight1: isDark ? "#BDB7B1" : "#554e48",
greyColor: isDark ? "#8F8982" : "#857f78",
linkColor: isDark ? "#7E9EDA" : "#92afe2",
borderColor: isDark ? "#5d5c5a" : "#eae0e0",
borderColorLight1: isDark ? "#383838" : "#eee",
};
});
</script>
页面使用
// 子组件
<template>
<g-page>
<g-statusbar title="关于我们"></g-statusbar>
<view class="about"></view>
</g-page>
</template>
<style scoped lang="scss">
.about {
background-color: var(--theme-bg-color);
color: var(--theme-primary-color);
}
</style>
webpack-theme-color-replace
- 之前公司项目中调研主题切换功能的实现的时候有了解过这个插件,这一种很不一样的实现思路
- 大概就是在webpack构建时,将即将生成的所有css文件的内容对指定颜色的规则的css单独提取出来,再合并为一个theme-colors.css输出文件。然后在切换主题色时,下载这个文件,并替换为需要的颜色,应用到页面上。
- 这篇文章对动态主题的实现有更多的介绍:
- webpack-theme-color-replace