vue+elementUI实现不同主题的切换(切换功能)

2,732 阅读2分钟

1617702631(1).jpg

element-ui 换肤功能

第一步 安装 element-ui 自定义主题相关插件

npm i element-theme-chalk -D
npm i element-theme -S

在assets文件夹中新建一个文件夹scss-temp 在assets文件夹中scss文件夹里的内容拷贝一份,粘贴到文件夹scss-temp中

第二步 安装 gulp 相关插件

npm i gulp-cli -g
npm i gulp-autoprefixer gulp-clean-css gulp-load-plugins gulp-rename gulp-sass -D

第三步 在跟目录创建一个 gulpfile.js 文件。不熟悉 API 的话,看一下 gulp 官方文档。下面为 gulpfile.js

var gulp = require("gulp");
var $ = require("gulp-load-plugins")();
var fs = require("fs");
var path = require("path");
var del = require("del");
//var colors = require('colors')
var child_process = require("child_process");

var theme = {};
var themeList = require("./src/element-ui/config.js").filter(
  (item) => !item.hasBuild
);
var styleFileDir = "./src/assets/scss";
var styleFileDirTemp = `${styleFileDir}-temp`;
var themeFileDir = "./public/element-theme";
var et = require("element-theme");
var etOptions = require("./package.json")["element-theme"];
var themeFileName = etOptions.config.replace(/.*\/(.+\.scss)/, "$1");

/**
 * 构建生成主题
 */
gulp.task("themes", () => {
  //console.log(colors.green('-------------------- 构建中,主题============= -------------------------'))
  if (themeList.length <= 0) {
    return del(styleFileDirTemp);
  }

  // 删除临时文件,保证本次操作正常执行
  //del(styleFileDirTemp)

  // 拷贝一份scss样式文件夹,作为构建的临时处理文件夹
  //child_process.spawnSync('cp', ['-r', styleFileDir, styleFileDirTemp])

  // 拷贝element组件scss变量样式文件至临时处理文件夹中,并修改相应配置信息
  //child_process.spawnSync('cp', ['-r', etOptions.config, styleFileDirTemp])
  etOptions.config = `${styleFileDirTemp}/${themeFileName}`;

  // 开始构建生成
  fnCreate(themeList);

  function fnCreate(themeList) {
    if (themeList.length >= 1) {
      // 保存当前构建生成的主题对象
      theme = themeList[0];

      console.log("\n");
      //console.log(colors.green('-------------------- 待构建,主题 -------------------------'))
      console.log(themeList);
      console.log("\n");
      //console.log(colors.green('-------------------- 构建中,主题 -------------------------'))
      console.log(theme);
      console.log("\n");

      // 修改.scss临时文件中的$--color-primary主题变量值
      var data = fs.readFileSync(etOptions.config, "utf8");
      var result = data.replace(
        /\$--color-primary:(.*) !default;/,
        `$--color-primary:${theme.color} !default;`
      );
      fs.writeFileSync(path.resolve(etOptions.config), result);

      // 修改aui.scss临时文件中引入element组件主题变量文件路径
      var data = fs.readFileSync(`${styleFileDirTemp}/aui.scss`, "utf8");
      var result = data.replace(
        new RegExp(`(@import \")(.*\/)(${themeFileName}\";)`),
        "$1./$3"
      );
      fs.writeFileSync(path.resolve(`${styleFileDirTemp}/aui.scss`), result);

      // 调用element-theme插件,生成element组件主题
      etOptions.out = `${themeFileDir}/${theme.name}`;
      et.run(etOptions, () => {
        // 生成后,构建同主题色aui.css项目主题
        gulp.start(["styles"], () => {
          // 递归下一步
          themeList.splice(0, 1);
          fnCreate(themeList);
        });
      });
    } else {
      // 删除临时文件
      del(styleFileDirTemp);
      console.log("\n");
      //console.log(colors.green('-------------------- 构建完毕,删除临时文件 -------------------------'))
      console.log(styleFileDirTemp);
      console.log("\n");

      // 删除主题不需要的部分文件
      var files = [
        `${themeFileDir}/**/*.css`,
        `!${themeFileDir}/**/index.css`,
        `!${themeFileDir}/**/aui.css`,
        `!${themeFileDir}/**/fonts`,
      ];
      del(files);
      //console.log(colors.green('-------------------- 构建完毕,删除主题独立组件文件 -------------------------'))
      console.log(files);
      console.log("\n");
    }
  }
});

gulp.task("styles", () => {
  return gulp
    .src([`${styleFileDirTemp}/aui.scss`])
    .pipe($.sass().on("error", $.sass.logError))
    .pipe(
      $.autoprefixer({
        browsers: etOptions.browsers,
        cascade: false,
      })
    )
    .pipe($.cleanCss())
    .pipe($.rename("aui.css"))
    .pipe(gulp.dest(`${themeFileDir}/${theme.name}`));
});

第四步

① 在 package.json 的 scripts 属性中加入以下命令

    "et": "node_modules/.bin/et",
    "et:init": "node_modules/.bin/et -i",
    "et:list": "gulp themes"

② 运行命令

npm run et:init

此时会在项目根目录下生成一个【element-variables.scss】的文件

③ 在 src 文件夹中创建一个 element-ui 的文件夹,将【element-variables.scss】移入 element-ui 文件夹中,并修改文件名称为:theme-variables.scss

④ 在 element-ui 文件夹中创建一个 config.js 文件,录入你需要的主题色,如下所示

/* eslint-disable */
/**
 * 主题配置信息
 *
 * hasBuild 是否已构建?
 *  true :已构建,不再构建
 *  false:未构建,执行命令后会自动构建
 */
module.exports = [
  { name: "default", color: "#409EFF", desc: "默认色", hasBuild: false },
  { name: "cyan", color: "#0BB2D4", desc: "青色", hasBuild: false },
  { name: "blue", color: "#3E8EF7", desc: "蓝色", hasBuild: false },
  { name: "green", color: "#11C26D", desc: "绿色", hasBuild: false },
  { name: "turquoise", color: "#17B3A3", desc: "蓝绿色", hasBuild: false },
  { name: "indigo", color: "#667AFA", desc: "靛青色", hasBuild: false },
  { name: "brown", color: "#997B71", desc: "棕色", hasBuild: false },
  { name: "purple", color: "#9463F7", desc: "紫色", hasBuild: false },
  { name: "gray", color: "#757575", desc: "灰色", hasBuild: false },
  { name: "orange", color: "#EB6709", desc: "橙色", hasBuild: false },
  { name: "pink", color: "#F74584", desc: "粉红色", hasBuild: false },
  { name: "yellow", color: "#FCB900", desc: "黄色", hasBuild: false },
  { name: "red", color: "#FF4C52", desc: "红色", hasBuild: false },
];

⑤ 在package.json新增属性element-theme

"element-theme": {
    "config": "./src/element-ui/theme-variables.scss",
    "out": "./src/element-ui/theme",
    "minimize": true,
    "browsers": [
      "> 1%",
      "last 2 versions",
      "not ie <= 10"
    ]
  }

⑥ 在public文件夹中创建创建文件夹:element-theme

⑦ 运行以下命令,会跑gulpfile.js中的代码

npm run et:list

修改主题色

修改 /src/assets/scss/variables-theme.scss ⽂件中 colorprimary变量值为--color-primary 变量值为 -- color-primary: blue !default; 保存。⻢上能在浏览器看到 主⼊⼝布局 头部背景⾊变成 蓝 ⾊

另开启⼀个 终端命令⾏ 切换到 项⽬根⽬录 执⾏ npm run et 命令。

组件中使用

<template>
  <div class="aui-theme-tools" :class="{ 'aui-theme-tools--open': isOpen }">
    <div class="aui-theme-tools__toggle" @click="isOpen = !isOpen">
      <svg class="icon-svg" aria-hidden="true"><use xlink:href="#icon-setting"></use></svg>
    </div>
    <div class="aui-theme-tools__content">
      <div class="aui-theme-tools__item">
        <h3>Navbar</h3>
        <el-checkbox v-model="$store.state.navbarLayoutType" true-label="colorful">colorful 鲜艳</el-checkbox>
      </div>
      <div class="aui-theme-tools__item">
        <h3>Sidebar</h3>
        <el-checkbox v-model="$store.state.sidebarLayoutSkin" true-label="dark">dark 黑色</el-checkbox>
      </div>
      <div class="aui-theme-tools__item">
        <h3>Theme</h3>
        <el-radio-group v-model="themeColor" @change="themeColorChangeHandle">
          <el-radio v-for="item in themeList" :key="item.name" :label="item.name">{{ `${item.name} ${item.desc}` }}</el-radio>
        </el-radio-group>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  data () {
    return {
      isOpen: false,
      themeList: require('@/element-ui/config.js'),
      themeColor: 'default'
    }
  },
  methods: {
    themeColorChangeHandle (val) {
      var styleList = [
        {
          id: 'J_elementTheme',
          url: `${process.env.BASE_URL}element-theme/${val}/index.css?t=${new Date().getTime()}`
        },
        {
          id: 'J_auiTheme',
          url: `${process.env.BASE_URL}element-theme/${val}/aui.css?t=${new Date().getTime()}`
        }
      ]
      for (var i = 0; i < styleList.length; i++) {
        var el = document.querySelector(`#${styleList[i].id}`)
        if (el) {
          el.href = styleList[i].url
          continue
        }
        el = document.createElement('link')
        el.id = styleList[i].id
        el.href = styleList[i].url
        el.rel = 'stylesheet'
        document.querySelector('head').appendChild(el)
      }
    }
  }
}
</script>