开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第18天,点击查看活动详情
前言
由于最近准备用 uniapp 开发一个新项目 pad 端的 app 项目,并且需要根据不同的子品牌实现一个换肤功能,于是尝试做了一个 uniapp 主题色切换的插件
需求
实现一个通用的theme类,配合<page>页面组件完成整个应用主题色配置,后续项目有类似需求可以直接套用
思路
通过在根组件配置相应主题的类名,以此修改组件内所有样式类的主题色
实现
定义主题颜色变量
修改uni.scss
/* 主题色 */
$default-theme: red;
$tx-theme: blue;
$white-text-color: #ffffff;
配置主题风格类
新建style文件夹,将类维护在一个 index.scss 文件中
.default-theme {
.theme-bg {
background-color: $default-theme;
}
.theme-btn {
background-color: $default-theme;
color: $white-text-color;
}
}
.tx-theme {
.theme-bg {
background-color: $tx-theme;
color: $white-text-color;
}
.theme-btn {
background-color: $tx-theme;
color: $white-text-color;
}
}
引入项目 App.vue
<style lang="scss">
/*每个页面公共css */
@import "style/index.scss";
</style>
创建页面容器组件
新建 page.vue 组件,作为所有页面的根组件,并在里面实现样式的切换逻辑
<template>
<view class="default-theme">
<slot></slot>
</view>
</template>
做一个 demo.vue 页面测试
<template>
<page>
<view class="theme-bg">
<text>测试</text>
</view>
<br>
<button class="theme-btn" @tap="test">请求</button>
</page>
</template>
可以看到我们配置的默认主题样式default-theme在页面中已经生效了,接下来只要切换根组件的样式类名,就可以实现切换效果了
主题切换方法
我们编写一个主题类,里面保存了我们的默认样式,并提供获取样式名,修改样式名的方法
import { ref } from 'vue'
class Theme {
constructor() {
this.theme = ref('default-theme')
}
get = () => {
return this.theme.value
}
change = (name) => {
this.theme.value = `${name}-theme`
}
}
export default Theme
全局注册
修改 main.js,将主题方法挂在 uni 对象上
import Theme from '@/lib/theme/index.js'
const theme = new Theme()
uni.$theme = theme
根组件样式配置
<template>
<view :class="theme">
<slot></slot>
</view>
</template>
<script>
export default {
computed: {
theme: () => {
return uni.$theme.get()
}
}
}
</script>
demo页面测试切换
methods: {
change() {
uni.$theme.change('tx')
}
}
数据持久化
这样一个主题切换的功能就实现了,但还有个小点,一般主题配置我们需要做本地缓存,我们把主题配置放在 storage 中
完整代码
- Theme.js
import { ref } from 'vue'
class Theme {
constructor() {
this.theme = ref(null)
this.init()
}
init = () => {
const theme = uni.getStorageSync('theme') || 'default-theme'
this.theme.value = theme
uni.setStorageSync('theme', theme)
}
get = () => {
return this.theme.value
}
change = (name) => {
this.theme.value = `${name}-theme`
uni.setStorageSync('theme', `${name}-theme`)
}
}
export default Theme
- Page.vue
<template>
<view :class="theme">
<slot></slot>
</view>
</template>
<script>
export default {
computed: {
theme: () => {
return uni.$theme.get()
}
}
}
</script>