vue + less 实现动态主题换肤功能


前言

在vue项目中(我的是2.6.11版本的)使用less做到切换主题肤色。话不多说,直接开始。

一、前提条件

1. 初始化vue项目

我这里的项目是2.6.11版本的

"vue": "^2.6.11",

2. 安装插件

安装一些less的插件

npm install less --save // less插件
npm install [email protected] --save // less-loader作用就是将less代码转译为浏览器可以识别的CSS代码。
npm install style-resources-loader -D // 在样式引入时,对于变量的引入,需要在每个文件里都要引入一遍,为了避免每次使用时都需要单独引入一遍的问题,采用了 style-resources-loader

二、新建文件夹主题theme

路径: src > assets > style > theme
翻译:theme 的中文就是主题
注意点:考虑到切换样式也是样式中的,所以放在style里面,当然,你可以放在任意位置,只要你后面的路径同一改了就好。

1.style.less文件

// 默认的主题颜色(白低黑字)
@baseColor: var(--baseColor, rgba(25,121,255));
@pageBgColor: var(--pageBgColor, rgba(255,255,255));
@scrollBgColor: var(--scrollBgColor, rgba(0, 0, 0));
@resultBgColor: var(--resultBgColor, rgba(255,192,203));
@resultBorderColor: var(--resultBorderColor, rgba(255,255,0));
@resultTextColor: var(--resultTextColor, rgba(0,0,0, 0.9));

// 导出变量 (如果在 src/assets/style/theme/model文件中配置了,就直接导出里面的字体使用)
:export {
    
    
  name: "less";
  baseColor: @baseColor;
  pageBgColor: @pageBgColor;
  scrollBgColor: @scrollBgColor;
  resultBgColor: @resultBgColor;
  resultBorderColor: @resultBorderColor;
  resultTextColor: @resultTextColor;
}

2.model.js文件

// 一套默认主题以及一套暗黑主题
export const themes = {
    
    
  default: {
    
    
    baseColor: `${
      
      25}, ${
      
      121},${
      
      255}`, // 基色(无变化) 
    pageBgColor: `${
      
      255}, ${
      
      255},${
      
      255}`, // 页面的背景色
    scrollBgColor: `${
      
      0}, ${
      
      0},${
      
      0}`, // 滚动条的背景色
    resultBgColor: `${
      
      255}, ${
      
      192},${
      
      203}`, // 结果背景色
    resultBorderColor: `${
      
      255}, ${
      
      255},${
      
      0}`, // 结果区背景色
    resultTextColor: `${
      
      0}, ${
      
      0},${
      
      0}, 0.9`, // 结果文字
  },
  dark: {
    
    
    baseColor: `${
      
      25}, ${
      
      121},${
      
      255}`, // 基色(无变化) 
    pageBgColor: `${
      
      0}, ${
      
      0},${
      
      0}`, // 页面的背景色
    scrollBgColor: `${
      
      255}, ${
      
      255},${
      
      255}`, // 滚动条的背景色
    resultBgColor: `${
      
      135}, ${
      
      206},${
      
      235}`, // 结果背景色
    resultBorderColor: `${
      
      0}, ${
      
      128},${
      
      0}`, // 结果区背景色
    resultTextColor: `${
      
      255}, ${
      
      255},${
      
      255}, 0.9`, // 结果文字
  },
};

3.theme.js文件

import {
    
     themes } from "./model";
// 修改页面中的样式变量值
const changeStyle = (obj) => {
    
    
  for (let key in obj) {
    
    
    document
      .getElementsByTagName("body")[0]
      .style.setProperty(`--${
      
      key}`, obj[key]);
  }
};
// 改变主题的方法
export const setTheme = (themeName) => {
    
    
  localStorage.setItem("theme", themeName); // 保存主题到本地,下次进入使用该主题
  const themeConfig = themes[themeName] ? themes[themeName] : themes['default'];
  changeStyle(themeConfig);
};

theme文件夹最终效果

在这里插入图片描述

三、修改vue.config.js文件

const path = require('path');
module.exports = {
    
    
  pluginOptions: {
    
    
    "style-resources-loader": {
    
    
      preProcessor: "less",
      patterns: [
        // 这个是加上自己的路径,不能使用(如下:alias)中配置的别名路径
        path.resolve(__dirname, "./src/assets/style/theme/style.less"),
      ],
    },
  },
};

注意: 修改vue.config.js文件 记得重新启动项目。

四、页面上的具体使用

1. index.vue 页面

<template>
  <div class="index">
    <button class="btn" @click="themeDefault">默认</button>
    <button class="btn" @click="themeDark">暗黑</button>
    <div class="content">
      这是一个可以切换主题的盒子
    </div>  
  </div>  
</template>

<script>
import {
    
     setTheme } from "../assets/style/theme/theme"; // 引入切换主题方法
export default {
    
    
  data() {
    
    
    return {
    
    
    }
  },
  methods: {
    
    
  // 默认主题方案(白底黑字)
    themeDefault() {
    
    
      document.documentElement.removeAttribute('theme-mode'); // 重置为浅色模式
      this.themeChange = true;
      setTheme("default"); // 初始化未默认主题
    },

    // 暗黑主题(黑底白字)
    themeDark() {
    
    
      document.documentElement.setAttribute('theme-mode', 'dark'); // 重置为深色模式
      this.themeChange = false;
      setTheme("dark");
    },
  },
  mounted: function() {
    
    
    this.themeDefault(); // 进入页面默认渲染默认主题方案
  }
}
</script>

<style lang="less" scoped>
@import '../assets/style/theme/style.less'; // 引入主题样式文件

.index{
    
    
  width: 100%;
  height: 100%;
  .btn {
    
    
    width: 50px;
    height: 30px;
    background-color: green;
  }
  .content {
    
    
    width: 100px;
    height: 100px;
    color: rgba(@resultTextColor, 1);
    background-color: rgba(@resultBgColor, 1);
    border: 10px solid  rgba(@resultBorderColor, 1);
  }
}
</style>

2. index.vue 页面注意点说明

在这里插入图片描述

3. index.vue 效果

(1)默认效果
在这里插入图片描述
(2)暗黑效果
在这里插入图片描述

其他校验修改主题成功的方法
在审查元素的body上有你所定义的数据就是了
在这里插入图片描述

五、在js中使用定义的颜色变量

1. 代码

import themsColor from '../assets/style/theme/style.less'; // 引入主题样式文件
export default {
    
    
  data() {
    
    
    return {
    
    
      themsColor,
    }
  },
  mounted: function() {
    
    
    console.log('themsColor', themsColor);
  }
}

2. 代码说明

在这里插入图片描述

3. 打印themsColor

在这里插入图片描述

六、关于定义颜色的变量不是十六进制的原因

如果你在modes.js中使用 #ffffff #333333 类似这样的颜色,其实也是可以的,而且在页面中可以直接使用 color: @resultTextColor,看过去似乎简单了很多,那为什么要改用rgb的方式呢?
相信有仔细注意代码的人可能注意到了这个颜色的值${255}, ${255},${255}, 0.9, 是的,透明度。
如果直接写死的十六进制的话,没有可以操作的空间。包括我实际项目最开始用的也是十六进制,后面才改成的rgb的方式。不仅仅是文字,包括颜色中也会有禁用等需要直接修改透明度的方法,不用因此再添加一个类似的变量考虑才使用的rgba的方法。当然,这也仅仅是一种思路。如果你有更好的方法可以忽略。
注意点:有透明度的就和颜色一样,加在后面就好了,没有透明度的话,就在后面加上1,不然可能没效果

猜你喜欢

转载自blog.csdn.net/weixin_44784401/article/details/132237441