[TOC]

需求背景:

单一的视觉不再满足用户(消费者)体验需求,为提高用户体验,因此提供主题切换(换肤)功能,允许用户将应用切换不同主题风格的皮肤,从而提高用户视觉效果及体验。

实现方式:

1. 根据根节点不同class进行切换

实现原理:

  • 准备多套主题色,如dark,default两套主题
  • 根据选择不同的主题色来切换根节点下的不同class ```css <!DOCTYPE html>

    当前主题色为:gray

<a name="yekLN"></a>
### 优点:

- 简单易懂,不需要额外技术支持
- 兼容性较好
<a name="DrVVk"></a>
### 劣势:

- 需维护多套主题,人工耗时较长
<a name="IVk6R"></a>
## 2. CSS变量
<a name="Q2uj2"></a>
### 实现原理:

- 创建具有全局作用域的变量,请在 :root(或其他元素)选择器中声明它
- 使用 var() 函数在样式表中插入变量的值
- 根据选择不同的主题去动态切换主题色
```css
<!DOCTYPE html>
<html lang="en">
  <head>
    <style>
      :root {
        --primary-color: gray;
      }
      div {
        width: 100px;
        height: 100px;
        background: var(--primary-color);
      }
    </style>
  </head>
  <body>
    <div></div>
    <p>当前主题色为:<span class="currentTheme">gray</span></p>
    <button onClick="toggleTheme()">主题色切换</button>
    <script>
      const themes = ["gray", "black"];
      function toggleTheme() {
        var currentTheme = getComputedStyle(document.documentElement)
          .getPropertyValue("--primary-color")
          .trim();
        var toggleTheme = themes.filter((_) => _ !== currentTheme)[0];
        document.documentElement.style.setProperty(
          "--primary-color",
          toggleTheme
        );
        document.querySelector(".currentTheme").innerText = toggleTheme;
      }
    </script>
  </body>
</html>

优点:

  • 使代码更易于阅读及理解
  • 动态切换更加简单

    劣势:

  • 兼容性较差

  • image.png

    3. 浏览器中less动态编译

    实现原理:

  • 找到项目所有的 less,并且将其中带有 less 的变量的选择器抽出,组合成一个新的 less,也就是 color.less

  • 在浏览器中通过 less.js 来编译他,然后覆盖掉原本的属性 ```css <!DOCTYPE html>

    当前主题色为:gray

<a name="GJpB5"></a>
### 优点:

- 支持任何颜色的主题切换
<a name="qF01H"></a>
### 劣势:

- 需额外加载less.js文件
- less编译工作在浏览器端进行,会比较消耗耗时且可能在换肤时出现白屏现象
<a name="MayzW"></a>
### 备注:
如直接打开对应Html文件,会报跨域问题,这是由于谷歌浏览器中的安全问题导致的<br />解决办法:本地启动web服务器
<a name="CkQKR"></a>
### less浏览器端编译实现:

- 初始化时调用registerStylesheetsImmediately方法,把当前引入的less文件放入less.sheets中
```css
less.registerStylesheetsImmediately()

var typePattern = /^text\/(x-)?less$/;
less.registerStylesheetsImmediately = function () {
  var links = document.getElementsByTagName('link');
  less.sheets = [];
  for (var i = 0; i < links.length; i++) {
    if (links[i].rel === 'stylesheet/less' || (links[i].rel.match(/stylesheet/) &&
    (links[i].type.match(typePattern)))) {
      less.sheets.push(links[i]);
    }
  }
};
  • 再调用其less.refresh方法 ```css less.pageLoadFinished = less.refresh(less.env === ‘development’);

less.refresh = function (reload, modifyVars, clearFileCache) { return new Promise(function (resolve, reject) { remainingSheets = less.sheets.length; if (remainingSheets === 0) { less.logger.info(‘Less has finished and no sheets were loaded.’); } else { loadStyleSheets(function (e, css, _, sheet, webInfo) { if (e) { errors.add(e, e.href || sheet.href); reject(e); return; } if (webInfo.local) { less.logger.info(“Loading “ + sheet.href + “ from cache.”); } else { less.logger.info(“Rendered “ + sheet.href + “ successfully.”); } browser.createCSS(window.document, css, sheet); less.logger.info(“CSS for “ + sheet.href + “ generated in “ + (new Date() - endTime) + “ms”); if (remainingSheets === 0) { resolve({ sheets: less.sheets.length }); } }, reload, modifyVars); } loadStyles(modifyVars); }); }; ```

  • 加载link标签中的文件
  • less文件编译成css文件
  • 生成style标签并插入到head头部

    4. 全局状态管理主题色(vue-element-admin)

    实现原理:

    优点:

    劣势: