解决的问题

实现一键切换 背景色、字体颜色、边框色、背景图等

实现思路

1.首先定义一个目录存储主题(固定如此): /static/theme/

  1. /static/theme/目录结构
  2. theme_dark.css // 只用于H5
  3. theme_light.css // 只用于H5
  4. theme_dark.js // 通用(包括小程序,H5等)
  5. theme_light.js // 通用(包括小程序,H5等)
  6. ├─dark
  7. bg_sidebar.jpg
  8. └─light
  9. bg_sidebar.jpg

theme_dark.css,theme_light.css 分别对应预设的两个主题包, 对应dark、light资源目录 文件中定义一些变量, 使用的地方引用即可

  1. :root{
  2. --primaryColor: #616161;
  3. --sidebarBg: url(/static/theme/dark/bg_sidebar.jpg)
  4. }

theme_dark.js,theme_light.js 分别对应预设的两个主题包, 对应dark、light资源目录

  1. export default {
  2. '--primaryColor': '#616161',
  3. '--sidebarBg': 'url(/static/theme/dark/bg_sidebar.jpg)',
  4. 'color': 'red'
  5. }

颜色处理: css中使用 primaryColor: #616161;

图片处理(背景、img):

css中使用 background: var(—sidebarBg) no-repeat 0 0;

view中使用

属性中使用 background-color=”var(—color-primary)”

【注意】 小程序背景图: 网络加载 或 base64

2.再定义一个变量存储当前主题, 此处使用vuex管理这个状态

  1. export default {
  2. state: {
  3. // 当前主题
  4. theme: uni.getStorageSync(KEY_THEME),
  5. // 支持主题列表, 读取/static/theme/theme_*.css 或 /static/theme/theme_*.js
  6. themeList: [], // 方便管理, 动态读取主题目录的下的主题文件, 方便后续扩展
  7. // 主题字典
  8. themeMap: {},
  9. // 是否H5模式, 默认false, 即采用适配所有通用模式
  10. isH5Mode: false
  11. }
  12. }

3.监听主题变化,加载对应主题【变更】

  1. computed: {
  2. ...mapState('theme', ['theme', 'themeList', 'locale', 'localeList', 'isH5Mode'])
  3. },
  4. methods: {
  5. onThemeChange(newVal, oldVal) {
  6. if (this.isH5Mode) {
  7. // 修改顺序, 防止切换过程中 当前主题 -> 默认主题(异常过程) -> 目标主题 (貌似第一次加载仍然存在)
  8. if (this.themeList.includes(newVal)) {
  9. loadCss(`/static/theme/theme_${newVal}.css`)
  10. }
  11. if (oldVal && this.themeList.includes(oldVal)) {
  12. removeCss(`/static/theme/theme_${oldVal}.css`)
  13. }
  14. } else {
  15. if (this.themeList.includes(newVal)) {
  16. this.$store.commit('theme/SET_THEME_MAP', require(`@/static/theme/theme_${newVal}.js`).default)
  17. }
  18. }
  19. }
  20. }

设置采用 ‘仅限H5’ 和 ‘ 通用’ 两种模式, 此处保留只为兼容, 调用
store.commit(‘theme/SET_H5_MODE’, !!isH5Mode)


4.使用

  1. // 步骤一、main.js 文件中引入
  2. import V587Theme from '@/uni_modules/v587-theme/plugin.js'
  3. // 传入store 实例, 指定默认主题:theme: 'light'
  4. Vue.use(V587Theme, {store, theme: 'light', isH5Mode: false })
  5. // 步骤二、App.vue 或任意使用的地方引入
  6. import themeMixin from '@/uni_modules/v587-theme/mixins/index.js'
  7. export default {
  8. mixins:[themeMixin]
  9. }
  10. // 步骤三 引入样式(可通用)
  11. computed: {
  12. ...mapGetters('theme',['themeMap']),
  13. }
  14. // 使用的地方root 节点添加style




5.默认主题


默认主题: store.theme.theme 不设置 或 设置为空

如何扩展?
可以在app.vue 中 配置扩展主题样式, 如