Sass切换主题

基于ele+vue开发切换主题颜色,ele自带不够完成业务开发故而研究sass补充开发


前言

基于ele+vue开发切换主题颜色,ele自带不够完成业务开发故而研究sass补充开发


提示:仅展示sass部分代码:

一、创建切换按钮?

示例:pandas 是基于NumPy 的一种工具,该工具是为了解决数据分析任务而创建的。

二、使用步骤

1.引入库

代码如下(示例) el-dropdown循环切换:

 <el-dropdown trigger="click">
      <span class="el-dropdown-link">
        主题
        <i class="el-icon-arrow-down el-icon--right" />
      </span>
      <el-dropdown-menu slot="dropdown">
        <el-dropdown-item
          v-for="item in Object.keys(themeList)"
          @click.native="themeFn(themeList[item].value, themeList[item].color)"
          :key="item"
        >
          <i :style="{ background: themeList[item].color }" class="colors"></i>
          {{ themeList[item].label }}
        </el-dropdown-item>
      </el-dropdown-menu>
    </el-dropdown>

不理解可看ele官方文档

themeList为数组

themeList:[
  0: { label: '默认', value: 'Construction', color: '#0066C5' },
  1: { label: '建设银行', value: 'Construction', color: '#0066C5' },
  2: { label: '中国银行', value: 'China', color: '#B50029' },
  3: { label: '交通银行', value: 'Its', color: '#00377A' },
  4: { label: '农业银行', value: 'NY', color: '#319C8B' },
  5: { label: '工商银行', value: 'GS', color: '#C7000A' },
  6: { label: '邮政银行', value: 'EMS', color: '#086547' }]
  
watch: { // data中定义变量theme
    async theme(val) {
      const oldVal = this.chalk ? this.theme : ORIGINAL_THEME
      if (typeof val !== 'string') return
      const themeCluster = this.getThemeCluster(val.replace('#', ''))
      const originalCluster = this.getThemeCluster(oldVal.replace('#', ''))
      this.$message({
        message: '  切换主题色中',
        customClass: 'theme-message',
        type: 'success',
        duration: 1500,
        iconClass: 'el-icon-loading'
      })

      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
        }
      }
      if (!this.chalk) {
        await this.getCSSString('chalk')
      }
      const chalkHandler = getHandler('chalk', 'chalk-style')

      chalkHandler()
      // 更改其他 style 标签 中的颜色
      // 但是需要刷新才能生效
      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.changeTheme(themeCluster)
      this.$emit('change', val)
      for (let i = 0; i < Object.values(themeList).length; i++) {
        if (
          Object.values(themeList)[i].color ==
          (val.indexOf('#') > 0 ? '#' + val : val)
        ) {
          this.themeFn(
            Object.values(themeList)[i].value,
            Object.values(themeList)[i].color
          )
        }
      }
    }
  },
   themeFn(value, color) {  //为函数
      this.$nextTick().then(() => {
        if (this.theme != color && color != undefined && color != null) {
          this.theme = color
        }
      })

      if (color) {
        window.document.documentElement.setAttribute('data-theme', value)
      } else {
        for (let i = 0; i < Object.values(themeList).length; i++) {
          if (
            Object.values(themeList)[i].color ==
            (this.theme.indexOf('#') != -1 ? this.theme : '#' + this.theme)
          ) {
            window.document.documentElement.setAttribute(
              'data-theme',
              Object.values(themeList)[i].value
            )
          }
        }
      }
    },

大概思路为在app的上面添加一个class 在切换过程中原生更改class来控制

sass部分截屏显示好了

请添加图片描述
创建按钮点击后给标签添加data-theme根据传递的参数来选定主题
请添加图片描述var.scss中定义四种变量对应不同变量的背景颜色及字体颜色请添加图片描述定义整体样式表中重复使用样式 其中为判断点击事件传递的参数来给予对应背景请添加图片描述页面中将 所有使用 $–color-primary 的变量值都换成对应背景颜色及字体

仅为自己开发回顾使用 仅提供思路 仿照可能会会报错哦

<template>
  <div>
    <el-dropdown trigger="click">
      <span class="el-dropdown-link">
        主题
        <i class="el-icon-arrow-down el-icon--right" />
      </span>
      <el-dropdown-menu slot="dropdown">
        <el-dropdown-item
          v-for="item in Object.keys(themeList)"
          @click.native="themeFn(themeList[item].value, themeList[item].color)"
          :key="item"
        >
          <i :style="{ background: themeList[item].color }" class="colors"></i>

          {{ themeList[item].label }}
        </el-dropdown-item>
      </el-dropdown-menu>
    </el-dropdown>
  </div>
</template>

<script>
// import axios from 'axios'
import { themeList } from '@/lib/map'
import { mapActions, mapGetters } from 'vuex'
import { getThemeScript } from '@/api/common/common.js'
import { ORIGINAL_THEME } from '@/lib/constant'

export default {
  data() {
    return {
      themeList,
      theme: '',
      chalk: '' // content of theme-chalk css
    }
  },
  computed: {
    ...mapGetters(['themeColor']) // 当前主题色
  },
  watch: {
    async theme(val) {
      const oldVal = this.chalk ? this.theme : ORIGINAL_THEME
      if (typeof val !== 'string') return
      const themeCluster = this.getThemeCluster(val.replace('#', ''))
      const originalCluster = this.getThemeCluster(oldVal.replace('#', ''))
      this.$message({
        message: '  切换主题色中',
        customClass: 'theme-message',
        type: 'success',
        duration: 1500,
        iconClass: 'el-icon-loading'
      })

      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
        }
      }
      if (!this.chalk) {
        await this.getCSSString('chalk')
      }
      const chalkHandler = getHandler('chalk', 'chalk-style')

      chalkHandler()
      // 更改其他 style 标签 中的颜色
      // 但是需要刷新才能生效
      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.changeTheme(themeCluster)
      this.$emit('change', val)
      for (let i = 0; i < Object.values(themeList).length; i++) {
        if (
          Object.values(themeList)[i].color ==
          (val.indexOf('#') > 0 ? '#' + val : val)
        ) {
          this.themeFn(
            Object.values(themeList)[i].value,
            Object.values(themeList)[i].color
          )
        }
      }
    }
  },
  created() {
    this.theme = this.themeColor ?? ''
    this.themeFn()
  },
  methods: {
    ...mapActions('setting', ['changeTheme']),
    updateStyle(style, oldCluster, newCluster) {
      let newStyle = style
      oldCluster.forEach((color, index) => {
        newStyle = newStyle.replace(new RegExp(color, 'ig'), newCluster[index])
      })
      return newStyle
    },

    async getCSSString(variable) {
      try {
        this[variable] = await getThemeScript()
      } catch (e) {}
    },
    themeFn(value, color) {
      this.$nextTick().then(() => {
        if (this.theme != color && color != undefined && color != null) {
          this.theme = color
        }
      })

      if (color) {
        window.document.documentElement.setAttribute('data-theme', value)
      } else {
        for (let i = 0; i < Object.values(themeList).length; i++) {
          if (
            Object.values(themeList)[i].color ==
            (this.theme.indexOf('#') != -1 ? this.theme : '#' + this.theme)
          ) {
            window.document.documentElement.setAttribute(
              'data-theme',
              Object.values(themeList)[i].value
            )
          }
        }
      }
    },
    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) => {
        let red = parseInt(color.slice(0, 2), 16)
        let green = parseInt(color.slice(2, 4), 16)
        let blue = parseInt(color.slice(4, 6), 16)

        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
    }
  }
  // methods: {

  // }
}
</script>

<style lang="scss">
.theme-message,
.theme-picker-dropdown {
  z-index: 99999 !important;
}

.theme-picker .el-color-picker__trigger {
  height: 26px !important;
  width: 26px !important;
  padding: 2px;
}

.theme-picker-dropdown .el-color-dropdown__link-btn {
  display: none;
}
.el-dropdown-menu__item .colors {
  display: inline-block;
  vertical-align: middle;
  width: 10px;
  height: 10px;
  border-radius: 50%;
}
</style>

 // 切换字体样式
@import './variables.scss'; 
@import './var.scss';
/* 自定义主题 借鉴var.scss定义变量 */
// 建设银行   #0066C5
$colors-Construction: (
  color-primary: #0066C5,  // 背景
  menu-color: #0066C5,  //字体颜色
  rgba-bg-color:rgba(0,102,197,.1),
  white-color: #ffffff,
); 
// 中国银行 #B50029
$colors-China: (
  color-primary: #B50029,
  menu-color: #B50029,
  rgba-bg-color:rgba(181,0,41,.1),
  white-color: #ffffff,
); 
// 交通银行 #00377A
$colors-Its: (
  color-primary: #00377A,
  menu-color: #00377A, 
  rgba-bg-color:rgba(0,55,122,.1),
  white-color: #ffffff,
); 
// 农业银行 #319C8B
$colors-NY: ( 
  color-primary: #319C8B,
  menu-color: #319C8B, 
  rgba-bg-color:rgba(49,156,139,.1),
  white-color: #ffffff,
); 
// 工商银行
$colors-GS: ( 
  color-primary: #C7000A,
  menu-color: #C7000A, 
  rgba-bg-color:rgba(199,0,10,.1),
  white-color: #ffffff,
); 
// 邮政银行
$colors-EMS: ( 
  color-primary: #086547,
  menu-color: #086547, 
  rgba-bg-color:rgba(8,101,71,.1),
  white-color: #ffffff,
); 
// 切换字体样式
// @import './variables.scss';
@import './var.scss';
// 切换模态框的背景色
/*
  参数介绍
  changeBgColor  -- 常用更改背景及字体颜色
  changeButton   -- 常用按钮更改背景字体边框
  changeColor    -- 常用更改字体颜色
  changeTabsItem -- 常用更改标题栏
*/
@mixin changeBgColor($key) {
   transition: border-color 0.3s, background-color 0.3s, color 0.3s;
    background: map-get($colors-Construction, $key) !important; 
  [data-theme="Construction"] & {
    transition: border-color 0.1s, background-color 0.1s, color 0.1s;
    background: map-get($colors-Construction, $key) !important; 
    border: none;
  }
  // 中国银行
  [data-theme="China"] & {
    transition: border-color 0.1s, background-color 0.1s, color 0.1s;
    background: map-get($colors-China, $key) !important; 
    border: none;
  }
  // 交通银行
  [data-theme="Its"] & {
    transition: border-color 0.1s, background-color 0.1s, color 0.1s;
    background: map-get($colors-Its, $key) !important; border: none;
  }
  // 农业银行
  [data-theme="NY"] & {
    transition: border-color 0.1s, background-color 0.1s, color 0.1s;
    background: map-get($colors-NY, $key) !important;  border: none;
  }
  // 工商银行
  [data-theme="GS"] & {
    transition: border-color 0.1s, background-color 0.1s, color 0.1s;
    background: map-get($colors-GS, $key) !important;  border: none;
  }
  // 邮政银行
  [data-theme="EMS"] & {
    transition: border-color 0.1s, background-color 0.1s, color 0.1s;
    background: map-get($colors-EMS, $key) !important; border: none;
  }
}
@mixin changeButton($key) {
  transition: border-color 0.3s, background-color 0.3s, color 0.3s;
    background: map-get($colors-Construction, $key) !important; 
    color: #fff;
    border: 1px solid map-get($colors-Construction, $key);

  [data-theme="Construction"] & {
    transition: border-color 0.3s, background-color 0.3s, color 0.3s;
    background: map-get($colors-Construction, $key) !important; 
    color: #fff;
    border: 1px solid map-get($colors-Construction, $key);
  }
  // 中国银行
  [data-theme="China"] & {
    transition: border-color 0.3s, background-color 0.3s, color 0.3s;
    background: map-get($colors-China, $key) !important; 
    color: #fff;
    border: 1px solid map-get($colors-China, $key);
  }
  // 交通银行
  [data-theme="Its"] & {
    transition: border-color 0.3s, background-color 0.3s, color 0.3s;
    background: map-get($colors-Its, $key) !important;
    color: #fff;
    border: 1px solid map-get($colors-Its, $key);
  }
  // 农业银行
  [data-theme="NY"] & {
    transition: border-color 0.3s, background-color 0.3s, color 0.3s;
    background: map-get($colors-NY, $key) !important; 
    color: #fff;
    border: 1px solid map-get($colors-NY, $key);
  }
  // 工商银行
  [data-theme="GS"] & {
    transition: border-color 0.3s, background-color 0.3s, color 0.3s;
    background: map-get($colors-GS, $key) !important; 
    color: #fff;
    border: 1px solid map-get($colors-GS, $key);
  }
  // 邮政银行
  [data-theme="EMS"] & {
    transition: border-color 0.3s, background-color 0.3s, color 0.3s;
    background: map-get($colors-EMS, $key) !important;
     color: #fff;
     border: 1px solid map-get($colors-EMS, $key);
  }
}
@mixin changeColor($key) {
  color: map-get($colors-Construction, $key)  !important;
  [data-theme="Construction"] & {
    color: map-get($colors-Construction, $key) !important;
  }
  // 中国银行
  [data-theme="China"] & {
    color: map-get($colors-China, $key) !important;
  }
   // 交通银行
  [data-theme="Its"] & {
    color: map-get($colors-Its, $key) !important;
  }
  // 农业银行
  [data-theme="NY"] & {
    color: map-get($colors-NY, $key) !important;
  }
  // 工商银行
  [data-theme="GS"] & {
    color: map-get($colors-GS, $key) !important;
  }
  // 邮政银行
  [data-theme="EMS"] & {
    color: map-get($colors-EMS, $key) !important;
  }
}
@mixin changeTabsItem($key) {
    transition: border-color 0.3s, background-color 0.3s, color 0.3s;
    background: map-get($colors-Construction, $key) !important; 
    color: #fff;
    border: 1px solid map-get($colors-Construction, $key);
  [data-theme="Construction"] & {
    transition: border-color 0.3s, background-color 0.3s, color 0.3s;
    background: map-get($colors-Construction, $key) !important; 
    color: #fff;
    border: 1px solid map-get($colors-Construction, $key);
  }
  // 中国银行
  [data-theme="China"] & {
    transition: border-color 0.3s, background-color 0.3s, color 0.3s;
    background: map-get($colors-China, $key) !important; 
    color: #fff;
    border: 1px solid map-get($colors-China, $key);
  }
  // 交通银行
  [data-theme="Its"] & {
    transition: border-color 0.3s, background-color 0.3s, color 0.3s;
    background: map-get($colors-Its, $key) !important;
    color: #fff;
    border: 1px solid map-get($colors-Its, $key);
  }
  // 农业银行
  [data-theme="NY"] & {
    transition: border-color 0.3s, background-color 0.3s, color 0.3s;
    background: map-get($colors-NY, $key) !important; 
    color: #fff;
    border: 1px solid map-get($colors-NY, $key);
  }
  
}
@mixin changeBorder($key) {
  border: 1px solid map-get($colors-Construction, $key);
  color:map-get($colors-Construction, $key) ;
[data-theme="Construction"] & {

  border: 1px solid map-get($colors-Construction, $key);
  color:map-get($colors-Construction, $key) ;
}
// 中国银行
[data-theme="China"] & {
  color:map-get($colors-China, $key) ;
  border: 1px solid map-get($colors-China, $key);
}
// 交通银行
[data-theme="Its"] & {
  color:map-get($colors-Its, $key) ;
  border: 1px solid map-get($colors-Its, $key);
}
}


借鉴:Sass应用之实现主题切换

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值