前端日积月累之换肤scss(完整代码)

331 阅读1分钟

一、安装依赖

npm install sass sass-loader -D
npm install vue-color // 引入颜色面板

二、配置scss全局自动注入

const { defineConfig } = require("@vue/cli-service");
module.exports = defineConfig({
  css: {
    loaderOptions: {
      sass: {
        //注意:sass-loader将文件引用写入每个组件,适合全局引入变量,但不适合在单页面应用中添加样式,如果是全局样式(非变量),建议在main.js里引入
        // 路径支持别名的写法,案例就是用了路径别名,如果你没有在项目里设置,也可以自己手动设置即可
        // sass-loader v10以下老版本 用的是prependData,不是additionalData
        // 给 sass-loader 传递选项
        // 默认情况下 `sass` 选项会同时对 `sass` 和 `scss` 语法同时生效
        // 因为 `scss` 语法在内部也是由 sass-loader 处理的
        // 但是在配置 `data` 选项的时候
        // `scss` 语法会要求语句结尾必须有分号,`sass` 则要求必须没有分号
        // 在这种情况下,我们可以使用 `scss` 选项,对 `scss` 语法进行单独配置
        additionalData: `@import "@/theme/style.scss";`,
      },
    },
  },
});

三、创建主题配置

image.png

3.1 创建主题scss变量

// style.scss

// 默认的主题颜色
$primaryColor: var(--primaryColor, (123, 42, 33));
$primaryTextColor: var(--primaryTextColor, skyblue);
// 导出变量
:export {
  name: "less";
  primaryColor: $primaryColor;
  primaryTextColor: $primaryTextColor;
}

3.2 创建主题配置文件

// model.js
// 一套默认主题以及一套暗黑主题
// 一套默认主题以及一套暗黑主题
export const themes = {
  default: {
    primaryColor: `${74}, ${144},${226}`,
    primaryTextColor: `${74}, ${144},${226}`,
  },
  dark: {
    primaryColor: `${0},${0},${0}`,
    primaryTextColor: `${0},${0},${0}`,
  },
};

3.3 创建主题切换文件

import { themes } from "./model";
// 修改页面中的样式变量值
const changeStyle = (obj) => {
  for (let key in obj) {
    document
      .getElementsByTagName("body")[0]
      .style.setProperty(`--${key}`, obj[key]);
  }
};
// 改变主题的方法
export const changeTheme = (themeName) => {
  themeName = themeName ? themeName : localStorage.getItem("theme") || "default";
  const themeConfig = themes[themeName];
  // 如果有主题名称,那么则采用我们定义的主题
  if (themeConfig) {
    localStorage.setItem("theme", themeName); // 保存主题到本地,下次进入使用该主题
    setTheme(themeConfig);
  } else {
    // 采用自定义
    customTheme();
  }
};

// 设置主题
export const setTheme = (themeConfig) => {
  localStorage.setItem("themeConfig", JSON.stringify(themeConfig)); // 保存主题色到本地
  changeStyle(themeConfig); // 改变样式
};

// 自定义主题
export const customTheme = (config) => {
  let themeConfig = localStorage.getItem("themeConfig")
    ? JSON.parse(localStorage.getItem("themeConfig"))
    : {};
  themeConfig = { ...themeConfig, ...config };
  localStorage.setItem("theme", "custom");
  setTheme(themeConfig);
};

3.4 创建vue文件,实现主题切换

<template>
  <div class="hello">
    <div class="box-1"></div>
    <div class="box-2"></div>
    <p>我是测试文字</p>
    <button @click="defaultTheme">默认主题</button>
    <button @click="dark">暗黑主题</button>
    <button @click="custom">自定义主题</button>
    <Chrome v-model="customColor" />
  </div>
</template>

<script>
import { changeTheme, customTheme } from "./theme/theme";
// 引入颜色面板
import { Chrome } from "vue-color";

export default {
  name: "HelloWorld",
  data() {
    return {
      customColor: {}, // 自定义颜色面板
    };
  },
  mounted() {
    this.init(); // 初始化主题
  },
  methods: {
    init() {
      changeTheme(); // 初始化未默认主题
    },
    // 更改为默认主题
    defaultTheme() {
      changeTheme("default");
    },
    // 更改为暗黑主题
    dark() {
      changeTheme("dark");
    },
    // 更改为自定义主题
    custom() {
      // 通过颜色面板自定义颜色
      const { rgba = {} } = this.customColor;
      if (!rgba.a) return;
      const primaryColor = `${rgba.r},${rgba.g},${rgba.b},${rgba.a}`;
      customTheme({ primaryColor });
    },
  },
  components: {
    Chrome,
  },
};
</script>
<style scoped lang="scss">
.hello {
  display: flex;
  flex-direction: column;
  align-items: center;
  .box-1 {
    width: 50px;
    height: 50px;
    margin-bottom: 30px;
    background: rgba($primaryColor);
  }
  .box-2 {
    width: 50px;
    height: 50px;
    margin-bottom: 30px;
    background: rgba($primaryTextColor);
  }
  p {
    color: $primaryTextColor;
  }
}
</style>

image.png

参考