当前位置:   article > 正文

Vue结合element UI后台管理系统实现一键换肤_vue一件换肤

vue一件换肤

总体构思

首先我们需要思考一个问题:后台管理系统一键换肤换的是哪些颜色?

  • 一般头部的的背景色、左侧菜单的背景色,菜单选中后的高亮色;
  • 有一些自己写的样式(不是用的组件库的)选中或者hover高亮的,或者用的组件库的组件,但是修改组建库里的一些默认颜色;
  • element ui 组件库主题色相应的修改;
    上面有3中情况,我们需要分开处理

1.头部和菜单背景色处理方案

虽然我们用了element UI的menu菜单组件,但是他默认可能就只有两种主题色,可能我们还需要其他的颜色,或者说一些表现更细粒度的颜色体现,细节更多,所以需要修改组件里面的一些颜色。
theme.scss

html[data-theme="red"] {
    // 菜单主题色
    .el-layouts-sider-light {
        background-color: #29343f;
    }
    .el-menus-light {
        background-color: #29343f;
        .el-submenus .el-menus {
            background-color: #29343f;
        }
        .el-menus-item-link {
            color: #CACFDC;
            background-color: #29343f;
            &:hover {
                background-color: #3d4d5d;
            }
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

这里只列举了一套背景色为red情况下菜单里面的各种颜色,还有其他颜色,你应该要知道。
可以看到,当html标签上的data-theme="red"的时候,就回去运用里面的样式,所以思路就是选择主题色的时候需要动态修改html上的data-theme属性

 document.documentElement.dataset.theme = selectTheme.fileName;
  • 1

2.自己写的一些样式,但是没有那么细粒度的去控制

自己写的一些样式,可以通过css变量的方式去控制,css变量的作用和用法这边不做赘述,具体可以百度查看,具体思路: 选择主题的时候动态给html标签添加style样式定义css变量

 const vars = Object.keys(selectTheme.colors).map(key => `--${key.slice(1)}:${selectTheme.colors[key]}`).join(';');
 document.documentElement.setAttribute('style', vars);
  • 1
  • 2

浏览器编译出来如下图:
在这里插入图片描述
现在就定义好了css变量,然后在代码中直接可以使用了
var.css

// 自定义变量
$body-bg: #f0f6fa;
$primary-color: var(--primary-color, #1990ff);
$primary-color-hover: var(--primary-color-hover, #42aaff);
$bg: var(--dark-theme-color, #32394d);
  • 1
  • 2
  • 3
  • 4
  • 5

因为使用sass预编译写的,用了sass变量的方式来引用,在代码中直接 sass变量 $primary-color,注意这里我们需要在vue.config.js中做个配置,才可直接使用sass变量
vue.config.js

css: {
    loaderOptions: {
      sass: {
        prependData: '@import "~@portal/common/lib/theme/vars.scss";'
      }
    }
  },
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

3.element ui组件里面主题色的切换

首先预先生产几套对应的css文件,放在public文件夹下,具体怎么生成,可查阅element UI的官网
在这里插入图片描述
然后切换的时候再动态的去引入对应的css文件

const themeLink = document.querySelector('link[rel=stylesheet][theme]');
 if (themeLink && themeLink.href.indexOf(selectTheme.fileName) === -1) {
    themeLink.href = themeLink.href.replace(/(\w)+\.css/, selectTheme.fileName + '.css');
  }
  • 1
  • 2
  • 3
  • 4

为了提高样式文件的加载速度,可以采用
预加载
页面资源预加载(Link prefetch)是浏览器提供的一个技巧,目的是让浏览器在空闲时间下载或预读取一些文档资源,用户在将来将会访问这些资源。一个Web页面可以对浏览器设置一系列的预加载指示,当浏览器加载完当前页面后,它会在后台静悄悄的加载指定的文档,并把它们存储在缓存里。当用户访问到这些预加载的文档后,浏览器能快速的从缓存里提取给用户。

入口文件index.html

<link href="<%= BASE_URL %>static/theme/default.css" rel=stylesheet theme>
<link href="<%= BASE_URL %>static/theme/blue.css" rel=prefetch as=style>
<link href="<%= BASE_URL %>static/theme/red.css" rel=prefetch as=style>
<link href="<%= BASE_URL %>static/theme/green.css" rel=prefetch as=style>
<link href="<%= BASE_URL %>static/theme/purple.css" rel=prefetch as=style>
  • 1
  • 2
  • 3
  • 4
  • 5

浏览器控制台查看请求可以看到
在这里插入图片描述

完整代码

vuex moudle theme.js

// initial state
import themeConfig from '@portal/common/lib/theme/config.js';
const state = {
  themeConfig,
  currentTheme: null
};
const getters = {
  currentTheme (state) {
    return state.currentTheme;
  },
  themeConfig (state) {
    return state.themeConfig;
  }
};

const actions = {
  initTheme (context) {
    const { commit, rootState, getters } = context;
    let themeInfo = JSON.parse(localStorage.getItem(`${rootState.auth.userInfo.LoginEmail}-theme`) || null);
    if (!themeInfo || !getters.themeConfig.find(item => item.name === themeInfo.name)) {
      themeInfo = { user: rootState.auth.userInfo.LoginEmail, name: 'default' };
    }
    commit('setCurrentTheme', themeInfo);
  },
  changeTheme (context, themeName) {
    const themeItem = state.themeConfig.find(item => item.name === themeName);
    const { commit, getters, rootState } = context;
    if (themeItem.name !== getters.currentTheme) {
      commit('setCurrentTheme', { user: rootState.auth.userInfo.LoginEmail, name: themeItem.name });
    }
  }
};

const mutations = {
  setCurrentTheme(state, themeInfo) {
    // todo 后边换成document.head
    const selectTheme = state.themeConfig.find(item => item.name === themeInfo.name);
    const themeLink = document.querySelector('link[rel=stylesheet][theme]');
    if (themeLink && themeLink.href.indexOf(selectTheme.fileName) === -1) {
      themeLink.href = themeLink.href.replace(/(\w)+\.css/, selectTheme.fileName + '.css');
    }
    const vars = Object.keys(selectTheme.colors).map(key => `--${key.slice(1)}:${selectTheme.colors[key]}`).join(';');
    document.documentElement.setAttribute('style', vars);
    document.documentElement.dataset.theme = selectTheme.fileName;
    localStorage.setItem(`${themeInfo.user}-theme`, JSON.stringify(themeInfo));
    state.currentTheme = themeInfo.name;
  }

};

export default {
  namespaced: true,
  state,
  getters,
  actions,
  mutations
};

  • 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
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58

config.js

export default [
  {
    name: 'blue',
    showName: '深邃蓝',
    fileName: 'blue',
    colors: {
      '$primary-color': '#4975FF',
      '$primary-color-hover': '#7299ff;',
      '$light-theme-color': '#3d4760',
      '$dark-theme-color': '#0A1431',
    }
  },
  {
    name: 'default',
    showName: '默认主题',
    fileName: 'default',
    colors: {
      '$primary-color': '#0068FE',
      '$primary-color-hover': '#2988ff',
      '$light-theme-color': '#fff',
      '$dark-theme-color': '#32394D',
    }
  },
  {
    name: 'green',
    showName: '孔雀绿',
    fileName: 'green',
    colors: {
      '$primary-color': '#2EC2AB',
      '$primary-color-hover': '#52cfb7',
      '$light-theme-color': '#46606f',
      '$dark-theme-color': '#07241E;',
    }
  },
  {
    name: 'red',
    showName: '玳瑁红',
    fileName: 'red',
    colors: {
      '$primary-color': '#F15548',
      '$primary-color-hover': '#fe7a74',
      '$light-theme-color': '#2c343f',
      '$dark-theme-color': '#2C343F',
    }
  },
  {
    name: 'purple',
    showName: '淡白紫',
    fileName: 'purple',
    colors: {
      '$primary-color': '#7A7DE5',
      '$primary-color-hover': '#a7acf2',
      '$light-theme-color': '#383a69',
      '$dark-theme-color': '#7A7DE5',
    }
  }
];

  • 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
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/IT小白/article/detail/462961
推荐阅读
相关标签
  

闽ICP备14008679号