使用vue的style的v-bind功能实现切换主题和修改主题色的功能

使用v-bind实现切换主题的功能

  1. 首先在store中保存一个主题色primary和当前使用的是哪个主题,保存其索引,切换主题的时候修改索引
    1
    2
    3
    4
    5
    6
    7
    8
    state: ():ILayout => ({
    setting: {
    theme: setting.theme !== undefined ? setting.theme : 0,
    color: {
    primary: setting.color !== undefined ? setting.color.primary : '#409eff'
    }
    }
    })
  2. 定义不同的主题
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    import { ITheme } from '/@/type/config/theme'
    import { useLayoutStore } from '/@/store/modules/layout'
    const theme:() => ITheme[] = () => {
    const { color } = useLayoutStore().getSetting
    return [
    {
    tagsActiveColor: '#fff',
    tagsActiveBg: color.primary,
    mainBg: '#f0f2f5',
    sidebarColor: '#fff',
    sidebarBg: '#001529',
    sidebarChildrenBg: '#000c17',
    sidebarActiveColor: '#fff',
    sidebarActiveBg: color.primary,
    sidebarActiveBorderRightBG: '#1890ff'
    },
    {
    tagsActiveColor: '#fff',
    tagsActiveBg: color.primary,
    navbarColor: '#fff',
    navbarBg: '#393D49',
    mainBg: '#f0f2f5',
    sidebarColor: '#fff',
    sidebarBg: '#001529',
    sidebarChildrenBg: '#000c17',
    sidebarActiveColor: '#fff',
    sidebarActiveBg: color.primary,
    sidebarActiveBorderRightBG: '#1890ff'
    }
    ]
    }
    export default theme
  3. 修改主题色具体代码changeThemeColor.ts,实现过程及部分代码参考的是vue-element-admin,实现思路是 需要拿到通过 package.json 拿到 element-plus 的版本号,根据该版本号去请求相应的样式。拿到样式之后将样色,通过正则匹配和替换,将颜色变量替换成你需要的,之后动态添加 style 标签来覆盖原有的 css 样式。
  4. /src/app.vue文件中初始调用一次changeThemeDefaultColor方法,判断是否修改默认主题色
  5. /src/app.vue文件中定义一个变量保存当前的主题,当主题色改变的时候或者主题切换的时候,再重新赋值
    1
    2
    3
    4
    5
    6
    7
    8
    9
    const { getSetting } = useLayoutStore()
    // 重新获取主题色
    const f = () => {
    let themeArray = theme()
    return getSetting.theme >= themeArray.length ? themeArray[0] : themeArray[getSetting.theme]
    }
    let themeStyle:Ref<ITheme> = ref(f())
    watch(() => getSetting.theme, () => themeStyle.value = f())
    watch(() => getSetting.color.primary, () => themeStyle.value = f())
  6. 然后在style中使用上面定义的主题即可获取,这样当主题改变的时候,下面的style中的样式也会跟着改变
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    .layout-sidebar-sidesetting > i {
    background-color: v-bind(themeStyle.sidebarActiveBg);
    color: v-bind(themeStyle.sidebarColor);
    }

    .layout-sidebar {
    background-color: v-bind(themeStyle.sidebarBg);

    .layout-sidebar-logo {
    background-color: v-bind(themeStyle.logoBg || themeStyle.sidebarBg);
    color: v-bind(themeStyle.logoColor || themeStyle.sidebarColor);
    }
    }
    // ...
  7. 如需在其他文件中使用该主题色
    • 先从store中获取主题色,再在js中定义变量保存主题色
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      import { useLayoutStore } from '/@/store/modules/layout'
      export default defineComponent({
      name: '...',
      setup() {
      const { color } = useLayoutStore().getSetting
      return {
      color
      }
      }
      })
    • 在style中使用
      1
      2
      3
      p {
      color: v-bind(color.primary);
      }

项目地址
项目示例