element如何动态切换主题(vite+vue+ts+elementPlus)

这篇具有很好参考价值的文章主要介绍了element如何动态切换主题(vite+vue+ts+elementPlus)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。


前言

提示:动态切换主题使用的是css3的var函数现实

示例:切换--main-bg-color的值,使用<div style="--main-bg-color:red"> </div> 那么当前标签下的所有节点使用到当前变量的都会发生变化

:root {
  --main-bg-color: coral;
}
 
#div1 {
  background-color: var(--main-bg-color);
}
 
#div2 {
  background-color: var(--main-bg-color);
}

一、elementui css变量都有哪些

element如何动态切换主题(vite+vue+ts+elementPlus)

 通过浏览器检查,发现element ui库的变量

二、如何修改这些变量

提示: 众所周知css是从上往下执行,如果我们可以在hand标签里最后一个添加一个style标签,是不是就可以重写掉element ui的变量

element如何动态切换主题(vite+vue+ts+elementPlus)

1.添加在head标签里面添加style标签(在main.ts添加如下代码)

代码如下(示例):

 

代码如下: 

const style = document.createElement("style");
style.innerText = ":root{--el-color-primary:red}";
document.head.appendChild(style);

可以发现elementui的主色调已经被我们替换为红色

三、如何动态修改颜色

 前言: 

  1. 查看element.sass源码可以发现,一个primary样式,可以生成多个渐变色
    $types: primary, success, warning, danger, error, info;
    @each $type in $types {
      @for $i from 1 through 9 {
        @include set-color-mix-level($type, $i, 'light', $color-white);
      }
    }
    
    // --el-color-primary-dark-2
    @each $type in $types {
      @include set-color-mix-level($type, 2, 'dark', $color-black);
    }

不难发现 --el-color-primary-dark-2变量 是当前primary颜色跟黑色混和百分之20生成的颜色

所以设置一个primary的颜色会生成会生成1-9的和白色混的渐变色,生产一个百分之20的和黑色混的颜色

那么我们的变量就分为俩种:

  推断类型: 通过一个主色调变量,生成n个渐变色

  键值类型:一个变量对应一个值 

直接上代码

定义数据类型

interface ThemeSetting {
  /**
   *element-ui Namespace
   */
  namespace: string;
  /**
   * 数据分隔符
   */
  division: string;
  /**
   * 前缀
   */
  startDivision: string;
  /**
   * 颜色外推设置
   */
  colorInferSetting: ColorInferSetting;
}

/**
 * 颜色混和设置
 */
interface ColorInferSetting {
  /**
   * 与白色混
   */
  light: Array<number>;
  /**
   * 与黑色混
   */
  dark: Array<number>;
  /**
   * 类型
   */
  type: string;
}

/**
 * 平滑数据
 */
interface KeyValueData {
  [propName: string]: string;
}
type UpdateInferData = KeyValueData;

type UpdateKeyValueData = KeyValueData;
/**
 *平滑数据
 */
interface InferData {
  /**
   * 设置
   */
  setting?: ColorInferSetting | any;
  /**
   * 健
   */
  key: string;
  /**
   * 值
   */
  value: string;
}

export type {
  KeyValueData,
  InferData,
  ThemeSetting,
  UpdateInferData,
  UpdateKeyValueData,
};

定义配置数据

import type { ThemeSetting } from "./type";
const setting: ThemeSetting = {
  namespace: "el",
  division: "-",
  startDivision: "--",
  colorInferSetting: {
    light: [3, 5, 7, 8, 9],
    dark: [2],
    type: "color",
  },
};
export default setting;

定义默认推断数据

import type { InferData } from "./type";
const inferDatas: Array<InferData> = [];
export default inferDatas;

定义默认键值数据

import type { KeyValueData } from "./type";
const keyValueData: KeyValueData = {
  "menu-item-height": "56px",
};
export default keyValueData;

编写动态修改主题代码

import type {
  ThemeSetting,
  InferData,
  KeyValueData,
  UpdateInferData,
  UpdateKeyValueData,
} from "./type";
import tinycolor from "@ctrl/tinycolor";

declare global {
  interface ChildNode {
    innerText: string;
  }
}
class Theme {
  /**
   * 主题设置
   */
  themeSetting: ThemeSetting;
  /**
   * 键值数据
   */
  keyValue: KeyValueData;
  /**
   * 外推数据
   */
  inferDatas: Array<InferData>;
  /**
   *是否是第一次初始化
   */
  isFirstWriteStyle: boolean;
  /**
   * 混色白
   */
  colorWhite: string;
  /**
   * 混色黑
   */
  colorBlack: string;

  constructor(
    themeSetting: ThemeSetting,
    keyValue: KeyValueData,
    inferDatas: Array<InferData>
  ) {
    this.themeSetting = themeSetting;
    this.keyValue = keyValue;
    this.inferDatas = inferDatas;
    this.isFirstWriteStyle = true;
    this.colorWhite = "#ffffff";
    this.colorBlack = "#000000";
  }

  /**
   * 拼接
   * @param setting 主题设置
   * @param names   需要拼接的所有值
   * @returns       拼接后的数据
   */
  getVarName = (setting: ThemeSetting, ...names: Array<string>) => {
    return (
      setting.startDivision +
      setting.namespace +
      setting.division +
      names.join(setting.division)
    );
  };

  /**
   * 转换外推数据
   * @param setting      主题设置对象
   * @param inferData    外推数据
   * @returns
   */
  mapInferMainStyle = (setting: ThemeSetting, inferData: InferData) => {
    const key: string = this.getVarName(
      setting,
      inferData.setting
        ? inferData.setting.type
        : setting.colorInferSetting.type,
      inferData.key
    );
    return {
      [key]: inferData.value,
      ...this.mapInferDataStyle(setting, inferData),
    };
  };
  /**
   * 转换外推数据
   * @param setting    设置
   * @param inferDatas 外推数据
   */
  mapInferData = (setting: ThemeSetting, inferDatas: Array<InferData>) => {
    return inferDatas
      .map((itemData) => {
        return this.mapInferMainStyle(setting, itemData);
      })
      .reduce((pre, next) => {
        return { ...pre, ...next };
      }, {});
  };
  /**
   * 转换外推数据
   * @param setting      主题设置对象
   * @param inferData    外推数据
   * @returns
   */
  mapInferDataStyle = (setting: ThemeSetting, inferData: InferData) => {
    const inferSetting = inferData.setting
      ? inferData.setting
      : setting.colorInferSetting;
    if (inferSetting.type === "color") {
      return Object.keys(inferSetting)
        .map((key: string) => {
          if (key === "light" || key === "dark") {
            return inferSetting[key]
              .map((l) => {
                const varName = this.getVarName(
                  setting,
                  inferSetting.type,
                  inferData.key,
                  key,
                  l.toString()
                );
                return {
                  [varName]: tinycolor(inferData.value)
                    .mix(
                      key === "light" ? this.colorWhite : this.colorBlack,
                      l * 10
                    )
                    .toHexString(),
                };
              })
              .reduce((pre, next) => {
                return { ...pre, ...next };
              }, {});
          }
          return {};
        })
        .reduce((pre, next) => {
          return { ...pre, ...next };
        }, {});
    }
    return {};
  };

  /**
   *
   * @param themeSetting 主题设置
   * @param keyValueData 键值数据
   * @returns            映射后的键值数据
   */
  mapKeyValue = (themeSetting: ThemeSetting, keyValueData: KeyValueData) => {
    return Object.keys(keyValueData)
      .map((key: string) => {
        return {
          [this.updateKeyBySetting(key, themeSetting)]: keyValueData[key],
        };
      })
      .reduce((pre, next) => {
        return { ...pre, ...next };
      }, {});
  };
  /**
   * 根据配置文件修改Key
   * @param key          key
   * @param themeSetting 主题设置
   * @returns
   */
  updateKeyBySetting = (key: string, themeSetting: ThemeSetting) => {
    return key.startsWith(themeSetting.startDivision)
      ? key
      : key.startsWith(themeSetting.namespace)
      ? themeSetting.startDivision + key
      : key.startsWith(themeSetting.division)
      ? themeSetting.startDivision + themeSetting.namespace
      : themeSetting.startDivision +
        themeSetting.namespace +
        themeSetting.division +
        key;
  };
  /**
   *
   * @param setting    主题设置
   * @param keyValue   主题键值对数据
   * @param inferDatas 外推数据
   * @returns 合并后的键值对数据
   */
  tokeyValueStyle = () => {
    return {
      ...this.mapInferData(this.themeSetting, this.inferDatas),
      ...this.mapKeyValue(this.themeSetting, this.keyValue),
    };
  };

  /**
   * 将keyValue对象转换为S
   * @param keyValue
   * @returns
   */
  toString = (keyValue: KeyValueData) => {
    const inner = Object.keys(keyValue)
      .map((key: string) => {
        return key + ":" + keyValue[key] + ";";
      })
      .join("");
    return `@charset "UTF-8";:root{${inner}}`;
  };

  /**
   *
   * @param elNewStyle 新的变量样式
   */
  writeNewStyle = (elNewStyle: string) => {
    if (this.isFirstWriteStyle) {
      const style = document.createElement("style");
      style.innerText = elNewStyle;
      document.head.appendChild(style);
      this.isFirstWriteStyle = false;
    } else {
      if (document.head.lastChild) {
        document.head.lastChild.innerText = elNewStyle;
      }
    }
  };

  /**
   * 修改数据并且写入dom
   * @param updateInferData   平滑数据修改
   * @param updateKeyvalueData keyValue数据修改
   */
  updateWrite = (
    updateInferData?: UpdateInferData,
    updateKeyvalueData?: UpdateKeyValueData
  ) => {
    this.update(updateInferData, updateKeyvalueData);
    const newStyle = this.tokeyValueStyle();
    const newStyleString = this.toString(newStyle);
    this.writeNewStyle(newStyleString);
  };

  /**
   * 修改数据
   * @param inferData
   * @param keyvalueData
   */
  update = (
    updateInferData?: UpdateInferData,
    updateKeyvalueData?: UpdateKeyValueData
  ) => {
    if (updateInferData) {
      this.updateInferData(updateInferData);
    }
    if (updateKeyvalueData) {
      this.updateOrCreateKeyValueData(updateKeyvalueData);
    }
  };

  /**
   * 修改外推数据 外推数据只能修改,不能新增
   * @param inferData
   */
  updateInferData = (updateInferData: UpdateInferData) => {
    Object.keys(updateInferData).forEach((key) => {
      const findInfer = this.inferDatas.find((itemInfer) => {
        return itemInfer.key === key;
      });
      if (findInfer) {
        findInfer.value = updateInferData[key];
      } else {
        this.inferDatas.push({ key, value: updateInferData[key] });
      }
    });
  };

  /**
   * 修改KeyValue数据
   * @param keyvalueData keyValue数据
   */
  updateOrCreateKeyValueData = (updateKeyvalueData: UpdateKeyValueData) => {
    Object.keys(updateKeyvalueData).forEach((key) => {
      const newKey = this.updateKeyBySetting(key, this.themeSetting);
      this.keyValue[newKey] = updateKeyvalueData[newKey];
    });
  };
}

export default Theme;

使用

// 引入主题对象
import Theme from "./theme";
// 引入默认推断数据
import inferDatas from "./theme/inferDatas";
// 引入默认keyValue数据
import keyValueData from "./theme/keyValueData";
// 引入设置对象
import setting from "./theme/setting";
const app = createApp(App);
// 创建主题对象
const theme = new Theme(setting, keyValueData, inferDatas);
// 将主题对象放到全局变量中
app.config.globalProperties.theme = theme;

其他组件使用

import { reactive, getCurrentInstance } from "vue";
import type { ComponentInternalInstance } from "vue";
const { appContext } = getCurrentInstance() as ComponentInternalInstance;
const theme = appContext.config.globalProperties.theme;
theme.updateWrite({ primary: form.themeColor });

API

- 修改推断数据

theme.updateWrite({
    primary: "#409eff",
    success: "#67c23a",
    warning: "#e6a23c",
    danger: "#f56c6c",
    error: "#f56c6c",
    info: "#909399",
  });

- 修改键值类型数据 

theme.updateWrite(undefined, {
    "--el-menu-active-color": "red",
    "--el-menu-bg-color": "pink",
    "--el-menu-item-height": "22px",
  });

- 一起修改

theme.updateWrite(
    {
      primary: "#409eff",
      success: "#67c23a",
      warning: "#e6a23c",
      danger: "#f56c6c",
      error: "#f56c6c",
      info: "#909399",
    },
    {
      "--el-menu-active-color": "red",
      "--el-menu-bg-color": "pink",
      "--el-menu-item-height": "22px",
    }
  );

总结:

  主题数据可以存储在数据库中,通过接口查询后调用函数修改即可完成动态主题文章来源地址https://www.toymoban.com/news/detail-401211.html

到了这里,关于element如何动态切换主题(vite+vue+ts+elementPlus)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • vue3+vite+ts视频背景酷炫登录模板【英雄联盟主题】

    最近我准备在自己的网站上开发一个博客系统,首先要实现后台登录界面。我选择使用Vue 3 + Vite + TypeScript框架来构建,下面是针对该主题的详细说明: 在网页中使用视频作为背景图已经相当常见了,而且网上也有很多相关的插件可供使用。我选择使用\\\"vue-responsive-video-backgr

    2024年02月15日
    浏览(45)
  • vue3 + TS + elementplus + pinia实现后台管理系统左侧菜单联动实现 tab根据路由切换联动内容

    效果图:  home.vue页面代码 left.vue页面代码 tab.vue页面代码 pinia里面的代码 安装 使用插件  在main.ts中注册 路由代码 我把代码放git上了,有需要的自行拉取 https://gitee.com/Flechazo7/vue3.git

    2024年02月09日
    浏览(48)
  • vue3+element Plus+ts 自定义主题色,以及生成主题色各种透明度

    目录 思路  安装css-color-function【接收一个颜色值,生成不同的透明度】 获取后台配置的主题色或者使用ColorPicker修改主题色  最终结果如下 本篇文章的主体思路是从element Plus官网引申而来。结合了我以前用vue2+element-ui配置主题色生成透明度(light-1至linght-9)的方法。 utils/

    2024年02月21日
    浏览(49)
  • vue3+vite+element-plus创建项目,修改主题色

    根据官方文档安装依赖 vite.config.js配置 新建一个文修改全局样式的文件 在src下新建styles/element/index.scss文件,内容如下: @forward \\\'element-plus/theme-chalk/src/common/var.scss\\\' with (     $colors: (         \\\'primary\\\': (             //主色             \\\'base\\\':green         )         //修改其他

    2024年02月10日
    浏览(51)
  • vite + vue + ts 自动按需导入 Element Plus组件,并如何解决按需引入后ElMessage与ElLoading 的问题(找不到名称“ElMessage”问题。)

    按需引入后ElMessage与ElLoading 的问题,两步优雅解决找不到名称“ElMessage”问题。不需要导入npm包,不需要下载任何东西,只要五行代码 目录 1、添加Element Plus组件库 1.2、下载 1.2、自动导入(官方推荐) 2、按需引入后ElMessage与ElLoading 的问题 2.1、解决问题 2.2、下面是分析原因

    2024年02月06日
    浏览(64)
  • 详解Vite创建Vue3项目+vue-router+ts+vite+element-plus

    前言 在之前的文章中写过“Vue3+TS+ElementPlus的安装和使用教程【详细讲解】”,但那篇文章写的是创建vue3的项目没有使用到Vite构建工具进行创建还是使用的常规webpacket构建工具进行创建的。提到Vite和webpacket的时候我们可以简单说一下。 Vite 和 Webpack 都是现代化的前端构建工

    2024年01月18日
    浏览(58)
  • vue3 + vite + ts + element-ui搭建后台管理框架

    vue3官网 vue3官网 vite vite官网连接 npm 安装 按照提示输出即可! vite 中使用 less 或 scss 安装后在style 中设置对应的 scss 或 less,推荐scss编译 安装less依赖 安装sass依赖 推荐使用插件,vite.config.js配置; unplugin-vue-components // 自动导入vue中hook reactive ref等AIP; unplugin-auto-import // 自动

    2024年02月15日
    浏览(60)
  • vue使用element-ui 实现多套自定义主题快速切换

    下载到本地项目文件 配置所需主题样式文件和className,例如上面代码:theme-black、theme-blue… 在根目录执行以下命令:

    2024年02月11日
    浏览(44)
  • vue3 element-plus 暗黑模式(主题切换)简易版

    暗黑模式是指在应用程序或操作系统中使用暗色背景和浅色文本的界面设计。与传统的亮色模式相比,暗黑模式具有以下特点: 减少眼部疲劳:使用暗色背景可以减少屏幕发出的蓝光,减轻长时间使用电子设备对眼睛的疲劳程度。这对于在晚上或低光环境下使用设备的人来说

    2024年02月08日
    浏览(60)
  • Vue3动态路由(Vite+Vue3+TS+Mock)

    Vue通过路由进行页面管理,不同的路由绑定到不同的页面。一般来说,前端直接写好的路由为静态路由,在不修改代码的情况下,路由表是不会改变的。对于不需要动态改变路由表的网站,静态路由就已经足够了,但是当页面需要与权限进行绑定时,不同用户允许浏览的页面

    2024年02月02日
    浏览(114)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包