基于element-ui 动态换肤的代码详解

1、在安装好element-ui@2.x 以后,首先安装sass-loader

npm i sass-loader node-sass -D

2、安装element-theme

npm i element-theme -D

3、安装theme-chalk

npm i element-theme-chalk -D
# or from github
npm i https://github.com/ElementUI/theme-chalk -D

4、初始化变量文件

et -i // 默认的文件是element-variables.scss,也可以自定义文件名 et --init [file path]

安装成功以后,在项目里会自动生成一个element-variables.scss 文件,如下图:

里面定义的是所有的颜色变量

当然,这一步也有可能失败,命令行提示找不到et 这个命令。这个时候需要按照步骤一,重新装一下sass-loader

5、修改变量

直接编辑 element-variables.scss 文件,例如修改主题色为红色

6、编译主题

保存文件后,到命令行里执行 et 编译主题,如果你想启用 watch 模式,实时编译主题,增加 -w 参数;如果你在初始化时指定了自定义变量文件,则需要增加 -c 参数,并带上你的变量文件名

此时,项目中会自动生成一个theme文件夹,里面是编译后所有的字体文件和样式文件

7、引入自定义主题

默认情况下编译的主题目录是放在 ./theme 下,你可以通过 -o 参数指定打包目录。像引入默认主题一样,在代码里直接引用 theme/index.css 文件即可。

import '../theme/index.css'
import ElementUI from 'element-ui'
import Vue from 'vue'

Vue.use(ElementUI)

启动项目,会发现原来默认的蓝色会变成红色

官网提供的这种方法仅适用于一次性的更改全局主题颜色,如果想实现官网2.0版本右上角,使用 ColorPicker 颜色选择器 动态换肤。那么建议参考vue-element-admin,作者的 《手摸手,带你用vue撸后台》系列文章非常精彩

ThemePicker.vue
<template>
  <el-tooltip effect="dark" content="theme" placement="bottom">
    <el-color-picker
    v-model="theme"
    class="theme-picker"
    size="small"
    popper-class="theme-picker-dropdown"/>
  </el-tooltip>
</template>
<script>
const version = require('element-ui/package.json').version // element-ui version from node_modules
const ORIGINAL_THEME = '#409EFF' // default color
export default {
  data() {
    return {
      chalk: '', // content of theme-chalk css
      theme: ORIGINAL_THEME
    }
  },
  watch: {
    theme(val, oldVal) {
      if (typeof val !== 'string') return
      const themeCluster = this.getThemeCluster(val.replace('#', ''))
      const originalCluster = this.getThemeCluster(oldVal.replace('#', ''))
      console.log(themeCluster, originalCluster)
      const getHandler = (variable, id) => {
        return () => {
          const originalCluster = this.getThemeCluster(ORIGINAL_THEME.replace('#', ''))
          const newStyle = this.updateStyle(this[variable], originalCluster, themeCluster)
          let styleTag = document.getElementById(id)
          if (!styleTag) {
            styleTag = document.createElement('style')
            styleTag.setAttribute('id', id)
            document.head.appendChild(styleTag)
          }
          styleTag.innerText = newStyle
        }
      }
      const chalkHandler = getHandler('chalk', 'chalk-style')
      if (!this.chalk) {
        const url = `https://unpkg.com/element-ui@${version}/lib/theme-chalk/index.css`
        this.getCSSString(url, chalkHandler, 'chalk')
      } else {
        chalkHandler()
      const styles = [].slice.call(document.querySelectorAll('style'))
        .filter(style => {
          const text = style.innerText
          return new RegExp(oldVal, 'i').test(text) && !/Chalk Variables/.test(text)
        })
      styles.forEach(style => {
        const { innerText } = style
        if (typeof innerText !== 'string') return
        style.innerText = this.updateStyle(innerText, originalCluster, themeCluster)
      })
      this.$message({
        message: '换肤成功',
        type: 'success'
  methods: {
    updateStyle(style, oldCluster, newCluster) {
      let newStyle = style
      oldCluster.forEach((color, index) => {
        newStyle = newStyle.replace(new RegExp(color, 'ig'), newCluster[index])
      return newStyle
    },
    getCSSString(url, callback, variable) {
      const xhr = new XMLHttpRequest()
      xhr.onreadystatechange = () => {
        if (xhr.readyState === 4 && xhr.status === 200) {
          this[variable] = xhr.responseText.replace(/@font-face{[^}]+}/, '')
          callback()
      xhr.open('GET', url)
      xhr.send()
    getThemeCluster(theme) {
      const tintColor = (color, tint) => {
        let red = parseInt(color.slice(0, 2), 16)
        let green = parseInt(color.slice(2, 4), 16)
        let blue = parseInt(color.slice(4, 6), 16)
        if (tint === 0) { // when primary color is in its rgb space
          return [red, green, blue].join(',')
        } else {
          red += Math.round(tint * (255 - red))
          green += Math.round(tint * (255 - green))
          blue += Math.round(tint * (255 - blue))
          red = red.toString(16)
          green = green.toString(16)
          blue = blue.toString(16)
          return `#${red}${green}${blue}`
      const shadeColor = (color, shade) => {
        red = Math.round((1 - shade) * red)
        green = Math.round((1 - shade) * green)
        blue = Math.round((1 - shade) * blue)
        red = red.toString(16)
        green = green.toString(16)
        blue = blue.toString(16)
        return `#${red}${green}${blue}`
      const clusters = [theme]
      for (let i = 0; i <= 9; i++) {
        clusters.push(tintColor(theme, Number((i / 10).toFixed(2))))
      clusters.push(shadeColor(theme, 0.1))
      return clusters
  }
}
</script>
Navbar.vue
<template>
  <el-menu class="navbar" mode="horizontal">
    <hamburger
      class="hamburger-container"
      :toggleClick="toggleSideBar"
      :isActive="!sidebar.opened">
    </hamburger>
    <div class="right-menu">
      <screenfull class="screenfull"></screenfull>
      <div class="lang">
        <el-dropdown>
          <i class="iconfont icon-language4"></i>
          <el-dropdown-menu slot="dropdown">
            <el-dropdown-item @click.native="toggleLang('zh')" :disabled="$i18n.locale == 'zh'">中文</el-dropdown-item>
            <el-dropdown-item @click.native="toggleLang('en')" :disabled="$i18n.locale == 'en'">English</el-dropdown-item>
          </el-dropdown-menu>
        </el-dropdown>
      </div>
      <theme-picker></theme-picker>
    </div>
  </el-menu>
</template>

以上demo代码地址:https://github.com/frwupeng517/element-admin

Element-UI 官方文档地址:http://element-cn.eleme.io/#/zh-CN/component/custom-theme

PanJiachen Git地址:https://github.com/PanJiaChen/vue-element-admin

到此这篇关于element-ui 动态换肤的文章就介绍到这了,更多相关element-ui 动态换肤内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • VUE+element-ui文件上传的示例代码

    目录 图片上传(ImageCropper) 文件上传(el-upload) 注意 图片上传(ImageCropper) 此前端代码自己封装了文件上传,只需要配置后端接口需求URL以及对应的图片上传成功后的处理函数,后端返回OSS生成的图片访问地址,然后cropsuccess函数将上传成功的图像进行显示. <template> <div class="app-container"> <!-- 讲师头像 --> <el-form-item labe

  • element-ui直接在表格中点击单元格编辑

    目录 实现效果 实现代码 最近由于公司开始使用elementUI,开发的过程中需要用到对表格的单元格进行编辑,下面是我自己实现表格可编辑的方式,感兴趣的可以了解一下 实现效果 编辑之后对应表格数据该字段值也就发生了变化,控制台输出所有数据即可查看变化 实现代码 1.自定义编辑组件 <template> <div class="editCell"> <div class="canEdit" v-if="CanEdit"

  • Vue element-ui表格内嵌进度条功能实现方法

    目录 一.引言 二.方法 三.实验结果与讨论 1.前期准备工作 2.实现功能 3完整实验代码 四.结语 一.引言 在着手做项目时,尤其是后台管理系统类的项目,不难会遇到,数据用进度条的形式呈现,可视化. 二.方法 本次实验主要应用element组件中的progress. 需要使用到属性: Type 进度条类型line/circle/dashboard :text-inside 进度条显示文字内置在进度条内(只在 type=line 时可用) :percentage 百分比(必填) :color

  • 详解element-ui 组件el-autocomplete使用踩坑记录

    项目遇到一个比较麻烦的需求,保存用户填写的历史记录,项目使用的element-ui,自然就使用了el-autocomplete组件,然后就是各种踩坑,以下记录以下写代码过程中遇到的问题 createFilter(queryString, filed) { console.log("createFilter==" + queryString) return (item) => { switch (filed) { case 'cardNum': break case 'cardPa

  • 关于vue中element-ui form或table lable换行的问题

    element-ui form或table lable换行问题 今天在写项目,突然遇到个需求,需要将form里面的lable换行,百度了下,发现了一个办法,特此记录下来 First,我们先要在我们的lable里面进行以下操作 :label="'机组: \n(xxx用)'" 双引号嵌套单引号 在需要换行的文字中间 加入\n 换行符 Second,再添加css的样式 /deep/ .el-form-item__label{ white-space:pre-line; } //如果是tabl

  • 基于element-ui 动态换肤的代码详解

    1.在安装好element-ui@2.x 以后,首先安装sass-loader npm i sass-loader node-sass -D 2.安装element-theme npm i element-theme -D 3.安装theme-chalk npm i element-theme-chalk -D # or from github npm i https://github.com/ElementUI/theme-chalk -D 4.初始化变量文件 et -i // 默认的文件是e

  • vue+element实现动态换肤的示例代码

    有时候一个项目的主题并不能满足所有人的审美,这时候换肤功能就很友好,本项目基于vue+element实现后台管理项目的换肤功能 1.创建换肤组件 <template> <el-color-picker class="theme-picker" popper-class="theme-picker-dropdown" v-model="theme" :predefine="predefineColors" &g

  • vue动态注册组件实例代码详解

    写本篇文章之前其实也关注过vue中的一个关于加载动态组件is的API,最开始研究它只是用来实现一个tab切换的功能,使用起来也蛮不错的. is 预期:string | Object (组件的选项对象) 用于动态组件且基于 DOM 内模板的限制来工作. 示例: <!-- 当 `currentView` 改变时,组件也跟着改变 --> <component v-bind:is="currentView"></component> 详见vue API中关于

  • mybatis动态sql实现逻辑代码详解

    目录 1.xml文件读取 2.xml 文件解析 mybatis通过将sql配置xml文件中,通过解析xml动态标签来实现动态sql 如下样例 xml文件 <?xml version = "1.0" ?> <!DOCTYPE script SYSTEM "script-1.0.dtd"> <script namespace="user"> <common id="commonOrder"

  • vue elementui el-form rules动态验证的实例代码详解

    一.介绍 简介:在使用elementUI el-form 中,对于业务不同的时候可能会产生不同表单结构,但是都是存在同一个表单控件el-form中. 图片介绍: 1.在用户选择单选或多选时会有A,B,C,D,E五个选项 2.在用户选择简答题时只会题干,答案以及解析选项(主要是通过v-if来进行判断) 问题引入:当用户选择不同的题库时会产生不同的form表单选项,这个时候在进行表单提交验证的时候就需要根据不同试题类型进行判断,这个时候就需要两个rules来动态进行表单校验. 解决方法:在页面加载的

  • Android Studio屏幕方向以及UI界面状态的保存代码详解

    项目:Orientation package com.example.orientation; import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.TextView; import androidx.appcompat.app.AppCompatActivity; public class M

  • Vue+Element switch组件的使用示例代码详解

    代码如下所示: <el-table-column label="商品状态" align="center"> <template slot-scope="{row}"> <el-switch v-model="row.goods_state" class="switch" :active-value="1" :inactive-value="0&qu

  • 基于ts的动态接口数据配置的详解

    需求前景 前端组件是可复用的,那么复用前端组件时从后端读取的数据源同样也需要可复用(后端api也要是配置化的方式进行),前端需要提供配置项给后端进行动态配置生成api. 具体实现流程 名词解析 mock 规范约束 使用的ts的 interface 进行编译前校验,所有的组件接收的 mock 结构,都必须是该 Interface 的实现 解析器 将mock打平成 key,value 结构的工具 eg. interface I_EchartOption { series: { data: { nam

  • Element实现动态表格的示例代码

    目录 [代码背景] [代码实现] #1# -> 代码复用的基础是你需要一个可复用的组件 #2# -> 在展示页面使用动态表格组件 #3# -> 如何给动态表格根据需求动态添加序号列/索引列 [代码背景] 有这样一个业务需求场景,有大概十几张表归属于某个类别,用户希望在同一个页面,通过选择不同的查询指标展示不同的表格,这些表的表头样式类似但是又不完全相同,怎么做呢? 到目前为止所有基于Element UI的表格样式都是直接在页面写死的,像官方这样: <el-table :data=&

  • 基于element UI input组件自行封装“数字区间”输入框组件的问题及解决

    目录 问题描述 实现效果 实现代码 问题描述 在开发时遇到一个数字区间输入框的需求,如下图: 项目使用的是vue,组件库用的是element UI,但是element UI并没有提供数字区间组件,只提供了InputNumber 计数器输入框,如果用两个计数器输入框进行拼接也能满足需求,但是样式调试起来太过于复杂且不够灵活,不能令人满意,并且该数字区间输入框在其它界面也有这种需求,于是就在element input输入框的基础上自行封装了一个数字区间组件使用. 实现效果 实现效果如下: 使用方式如

随机推荐