解决的问题
实现思路
1.首先定义一个目录存储主题(固定如此): /static/theme/
/static/theme/目录结构
│ theme_dark.css // 只用于H5
│ theme_light.css // 只用于H5
│ theme_dark.js // 通用(包括小程序,H5等)
│ theme_light.js // 通用(包括小程序,H5等)
│
├─dark
│ bg_sidebar.jpg
│
└─light
bg_sidebar.jpg
theme_dark.css,theme_light.css 分别对应预设的两个主题包, 对应dark、light资源目录 文件中定义一些变量, 使用的地方引用即可
:root{
--primaryColor: #616161;
--sidebarBg: url(/static/theme/dark/bg_sidebar.jpg)
}
theme_dark.js,theme_light.js 分别对应预设的两个主题包, 对应dark、light资源目录
export default {
'--primaryColor': '#616161',
'--sidebarBg': 'url(/static/theme/dark/bg_sidebar.jpg)',
'color': 'red'
}
颜色处理: css中使用 primaryColor: #616161;
图片处理(背景、img):
css中使用 background: var(—sidebarBg) no-repeat 0 0;
view中使用
属性中使用 background-color=”var(—color-primary)”
【注意】 小程序背景图: 网络加载 或 base64
2.再定义一个变量存储当前主题, 此处使用vuex管理这个状态
export default {
state: {
// 当前主题
theme: uni.getStorageSync(KEY_THEME),
// 支持主题列表, 读取/static/theme/theme_*.css 或 /static/theme/theme_*.js
themeList: [], // 方便管理, 动态读取主题目录的下的主题文件, 方便后续扩展
// 主题字典
themeMap: {},
// 是否H5模式, 默认false, 即采用适配所有通用模式
isH5Mode: false
}
}
3.监听主题变化,加载对应主题【变更】
computed: {
...mapState('theme', ['theme', 'themeList', 'locale', 'localeList', 'isH5Mode'])
},
methods: {
onThemeChange(newVal, oldVal) {
if (this.isH5Mode) {
// 修改顺序, 防止切换过程中 当前主题 -> 默认主题(异常过程) -> 目标主题 (貌似第一次加载仍然存在)
if (this.themeList.includes(newVal)) {
loadCss(`/static/theme/theme_${newVal}.css`)
}
if (oldVal && this.themeList.includes(oldVal)) {
removeCss(`/static/theme/theme_${oldVal}.css`)
}
} else {
if (this.themeList.includes(newVal)) {
this.$store.commit('theme/SET_THEME_MAP', require(`@/static/theme/theme_${newVal}.js`).default)
}
}
}
}
设置采用 ‘仅限H5’ 和 ‘ 通用’ 两种模式, 此处保留只为兼容, 调用
store.commit(‘theme/SET_H5_MODE’, !!isH5Mode)
4.使用
// 步骤一、main.js 文件中引入
import V587Theme from '@/uni_modules/v587-theme/plugin.js'
// 传入store 实例, 指定默认主题:theme: 'light'
Vue.use(V587Theme, {store, theme: 'light', isH5Mode: false })
// 步骤二、App.vue 或任意使用的地方引入
import themeMixin from '@/uni_modules/v587-theme/mixins/index.js'
export default {
mixins:[themeMixin]
}
// 步骤三 引入样式(可通用)
computed: {
...mapGetters('theme',['themeMap']),
}
// 使用的地方root 节点添加style
5.默认主题
默认主题: store.theme.theme 不设置 或 设置为空
如何扩展?
可以在app.vue 中 配置扩展主题样式, 如