前言
由于最近准备用 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>