hgq's docs
主页
ES6-阮一峰 (opens new window)
Vue文档 (opens new window)
Axios文档 (opens new window)
Vue Router (opens new window)
Vuex文档 (opens new window)
面试题-Vue (opens new window)
面试题-JS (opens new window)

guoguoqiqi

漫不经心的向往
主页
ES6-阮一峰 (opens new window)
Vue文档 (opens new window)
Axios文档 (opens new window)
Vue Router (opens new window)
Vuex文档 (opens new window)
面试题-Vue (opens new window)
面试题-JS (opens new window)
  • 常用的调试代码方法
  • 每日一题集合
  • 前端换肤的解决方案
    • 其它
    guoguoqiqi
    2022-04-26

    前端换肤的解决方案

    image

    这是五种均为通用方案,可以适用于各种前端框架,脚手架中

    # 一、 利用class 命名空间

    这是最简单的换肤方式, 看下面示例即可轻松理解。

    1. 利用class 名称准备两个主题:
    p.red-theme {
      color: red;
    }   
    
    p.blue-theme {
      color: blue;
    }
    
    1
    2
    3
    4
    5
    6
    7
    1. 如果用红色主题, 给body增加 red-theme标签
     <body class="red-theme">     <p> 这里是红色主题 </p>      ... </body> 
    
    1
    1. 如果用蓝色主题, 用 blue-theme 代替 red-theme
     <body class="blue-theme">     <p> 这里是蓝色主题 </p>      ... </body> 
    
    1

    # 优缺点

    • 优点: 简单,好理解,好实现
    • 缺点: CSS中需多写主题的class,代码容易混乱;需手动编写

    # 参考

    基于element动态换肤 (opens new window)

    # 二、 准备多套CSS主题

    本地存放多套主题, 根据需要切换加载不同的样式

    1. 准备一份默认样式主题
    /*theme-default.css*/
    p { color: #333 }
    
    1
    2
    1. 准备各主题的样式
    /* theme-red.css */
    p { color: red }
    
    1
    2
    /* theme-blue.css */
    p { color: blue }
    
    1
    2
    1. 页面加载后,根据用户需求加载不同的样式列表
       var link = document.createElement('link');
       link.type = 'text/css';
       link.id = "theme-blue";
       link.rel = 'stylesheet';
       link.href = '/css/theme-blue.css';
       document.getElementsByTagName("head")[0].appendChild(link);
    
    1
    2
    3
    4
    5
    6
    1. 有时候需要保存用户使用的主题,可以通过如下方式:
      • 利用路由标记
      • 利用cookie标记
      • 利用localstorage
      • 保存到后端服务器

    # 优缺点

    • 优点: 简单,好理解,好实现
    • 缺点: 需要手写两份以上CSS配色样式; 切换样式需要下载CSS的时间

    # 参考

    web网页中主题切换的实现思路 (opens new window) 中有更多细节

    # 三、 利用CSS预处理生成多套主题样式

    这是“准备多套CSS主题”的优化方案,利用CSS预处理生成多套主题样式,再根据需要切换

    1. 利用Less,stylus 或 sass 的变量代替颜色值
    2. 配置多个主题颜色配置
    3. 利用webpack等工具输出多套主题样式
    4. 页面加载后,根据用户需求加载不同的样式列表(同方案2)

    # 优缺点

    • 优点: 不用手写两套CSS
    • 确定: 配置复杂;生成冗余的CSS文件; 切换样式需要下载CSS的时间

    # 参考

    webpack的配置比较复杂,可以看这篇文章:webpack 换肤功能多主题/配色样式打包解决方案 (opens new window)
    ant 环境下可以利用antd-theme-generator 快速配置,详见:antd-theme-generator (opens new window),antd在线换肤定制功能 (opens new window)

    # 四、 动态换肤

    这是element ui中的换肤方案,支持浏览器热换肤。生成一套主题, 将主题配色配置写在js中,在浏览器中用js动态修改style标签覆盖原有的CSS。

    1. 准备一套默认theme.css样式
    /* theme.css */
    .title { color: #FF0000 }
    
    1
    2
    1. 准备主题色配置
    var colors = {
    	red: { themeColor: "#FF0000" },
    	blue: { themeColor: "#0000FF" },
    };
    
    1
    2
    3
    4
    1. 异步获取 theme.css ,将颜色值替换为关键词
      关键字可以确保以后能多次换色
    var styles = ''
    axios.get('theme.css').then((resp=> {
     const colorMap = {
       '#FF0000': 'themeColor'
     }
     styles = resp.data
     Object.keys(colorMap).forEach(key => {
       const value = colorMap[key]
       styles = styles.replace(new RegExp(key, 'ig'), value)
     })
    }))
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11

    style 变为:

    .title { color: theme-color }
    
    1
    1. 把关键词再换回刚刚生成的相应的颜色值,并在页面上添加 style 标签
     // console 中执行 writeNewStyle (styles, colors.blue)  即可变色
     function writeNewStyle (originalStyle, colors) {
        let oldEl = document.getElementById('temp-style')
        let cssText = originalStyle
          // 替换颜色值
        Object.keys(colors).forEach(key => {
          cssText = cssText.replace(new RegExp(key, 'ig'), colors[key])
        })
        const style = document.createElement('style')
        style.innerText = cssText
        style.id = 'temp-style'
    
        oldEl ? document.head.replaceChild(style, oldEl) : 
        document.head.appendChild(style)  // 将style写入页面
      }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15

    此时style 变为:

    .title { color: '#0000FF' }
    
    1

    # 优缺点

    • 优点: 只需一套CSS文件; 换肤不需要延迟等候;可自动适配多种主题色;
    • 缺点: 稍难理解; 需准确的css颜色值;可能受限于浏览器性能;

    # 参考

    本文最后有该方案的完整代码
    Vue 换肤实践 (opens new window)
    elementUI 及 vuetifyjs动态换色实践 (opens new window)
    vue-element-admin 动态换肤 (opens new window)
    webpack 插件抽取CSS中的主题色 (opens new window)

    # 五、 CSS 变量换肤

    利用CSS 变量设置颜色, 用js动态修改CSS变量,进而换色。
    如果不考虑IE兼容,这是最佳换肤方案
    看下面的例子,很好理解

    <html>
      <head>
        <title>CSS varies</title>
        <style>
          :root {
            --theme-color: red /* css 变量赋值位置 */
          }
          .title {
            color: var(--theme-color) /* 用css变量标记颜色 */
          }
        </style>
      </head>
      <body>
        <h3 class="title">CSS 变量换肤</h3>
        <script>
          // console 中执行 changceColor('blue') 即可变色
          function changeColor(color = 'blue') {
            document.documentElement.style.setProperty("--theme-color",color);
          }
        </script>
      </body>
    </html>
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22

    # 优缺点

    • 优点:只需一套CSS文件; 换肤不需要延迟等候;对浏览器性能要求低;可自动适配多种主题色;
    • 缺点: 不支持IE, 2016年前的chrome,safari; 兼容性参见Can I Use CSS Variables (opens new window)

    # 参考

    • 使用CSS3自定义属性实现换肤功能 (opens new window)

    # 参考文章链接

    前端换肤方案 (opens new window)

    ← 每日一题集合

    最近更新
    01
    vuex数据持久化怎么做
    05-22
    02
    vue的动态路由怎么配置使用
    05-22
    03
    vue权限控制一般怎么做
    05-22
    更多文章>
    Theme by Vdoing | Copyright © 2022-2022 Guoquoqiqi | MIT License
    • 跟随系统
    • 浅色模式
    • 深色模式
    • 阅读模式