当前位置:   article > 正文

基于element-ui的主题换肤_vue 基于element ui设置皮肤单选

vue 基于element ui设置皮肤单选

今天分享的是基于element-ui的主题换肤功能

需求

效果如动图:在这里插入图片描述

需求描述:根据客户的个人喜好,切换不同颜色风格的主题。

关键点1:在element-ui官方去配置主题颜色并且下载对应的文件,一定是要和ui给的颜色相对应。

关键点2:实现切换功能函数,调用接口,保存用户的选择。(这是优化之后,最开始做的是保存在本地,但是产品认为应该保存下来,让用户在其他地方登录也能够展现自己之前的选择)

关键点3:所有与主题相关的颜色(背景、边框、下划线、特殊字体等)全部用变量来控制。项目用的less语法所以用的@*****。

第一步:下载配置文件

在这里插入图片描述
在这里插入图片描述
ps:第一张图红色框内为自定义主题内,相关组件的颜色,设置好后点击下载,下载好的文件包含css文件和字体文件。第二张图就是配置好对应颜色的主题静态文件。

第二步:实现切换功能
1、皮肤组件代码(不包含样式代码,不然太长了)
<template>
  <div class="color" @click.stop>
    <el-scrollbar style="height: 100%;">
      <div class="dropMeau">
        <div class="headerLine">
          经典皮肤 {{getSkinName}}
        </div>
        <div class="wrapCell">
          <div class="colorSkinWrap" v-for="(item,i,k) in  themeList">
            <span finger @click="changeColor(item.themeName)" :style="{background: computedBgc(item) }" class="colorSkin " :class="{active:getSkinName==item.themeName}" style=" background: #042663;">
              <span class="icon-yiwancheng iconfont"></span>
            </span>
            <p class="name">{{item.themeName}}</p>
          </div>
        </div>
      </div>
    </el-scrollbar>
  </div>
</template>

<script>
import themeList from '@libs/css/style.js'   // 定义颜色的js文件,里面包含了颜色,特殊的图片地址
import { mixin } from "@libs/mixs.js"; 
import {
  mapActions,
  mapGetters
} from 'vuex'
export default {
  name: "messageQuick",
  mixins: [mixin],
  data() {
    return {
      themeName: '',
      themeList,
    }
  },
  computed: {
    ...mapGetters('info', ['getSkinName']), // 存在vux中的颜色变量属性
  },
  created() {
  },
  methods: {
    ...mapActions('info', [
      'actionSkinChange'   
    ]),
    computedBgc(item) {
      if (item.spec) {
        return `${item.style['--primary-color']} url('${item.showBox}')`
      } else {
        return item.style['--primary-color']
      }
    },
    changeColor(name) {   //主题 跳转页面判断皮肤换肤

      if (name != this.getSkinName) {
        this.axios({
          url: "/service-user-app/app/user/config/skin/peeler",  // 保存用户的选择接口
          method: "post",
          params: {
            colour: name
          },
          interface: 1
        }).then(res => {
          let data = res.data
          if (data.code == 0) {
              this.actionSkinChange(name)   // 更改vux中的默认颜色值
              this.setStyleRoot(name, themeList)  // 更改主题色
          }
        })
      }
    }
  },
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
2、themeList颜色代码(里面有11种颜色的配置属性,我只取了两个典型)
export default  [
  {
    "themeName": "绀青",
    // gangqing
    "src": "/static/theme/gangqing/index.css",
    "style": {
      "--primary-color": "#245BBF",
      "--table-header-bcolor": "#F7F7F7",
      "--primary-mix05": "#CFD5E0",
      "--primary-mix1": "#CFD5E0",
      "--primary-mix2": "#BDC8DC",
      "--primary-mix3": "#A9BAD9",
      "--primary-mix4": "#97ADD5",
      "--primary-mix5": "#849FD2",
      "--primary-mix6": "#7091CD",
      "--primary-mix7": "#5D83CA",
      "--primary-mix8": "#4A76C6",
      "--primary-mix9": "#3769C3",

      /* 导航栏 */
      "--nav-backgroud-color": "#042663",
      "--nav-ul-backgroud-color": "#fff",
      "--nav-ul-font-color": "#333",
      "--nav-ul-active-backgroud-color": "#D8E6FF",
      "--nav-ul-active-font-color": "#333",


      /* 头部颜色*/
      "--header-backgroud-color": "#042663",
    }
  },
// todo   加图片
  {
    "themeName": "紫棠",
    // zitang
    "spec":true,
    "showBox":'/static/img/zitang.png',
    "src": "/static/theme/zitang/index.css",
    "style": {
      "--primary-color": "#78359A",
      "--table-header-bcolor": "#F7F7F7",
      "--primary-mix05": "#F1EAF5",
      "--primary-mix1": "#F1EAF5",
      "--primary-mix2": "#E4D6EB",
      "--primary-mix3": "#D6C2E0",
      "--primary-mix4": "#C9AED6",
      "--primary-mix5": "#BB99CC",
      "--primary-mix6": "#AE85C2",
      "--primary-mix7": "#A071B8",
      "--primary-mix8": "#935DAE",
      "--primary-mix9": "#8548A3",

      /* 导航栏 */
      // "--nav-backgroud-color": "#531659",
      "--nav-backgroud-color": "#531659 url('/static/img/zitang1.jpg')",
      "--nav-ul-backgroud-color": "#fff",
      "--nav-ul-font-color": "#333",
      "--nav-ul-active-backgroud-color": "#F6EAFC",
      "--nav-ul-active-font-color": "#333",


      /* 头部颜色*/
      // "--header-backgroud-color": "#531659",
      "--header-backgroud-color": "#531659 url('/static/img/zitang2.jpg')",
    }
  },
]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67

ps:因为代码太多,所以抽成了js文件,我只取了其中两种有区别颜色的代码段(完整的有11种,和页面上的一样),有 “spec”:true,属性的颜色,就是带有花纹的主题,而不是普通的素颜色主题。

3、vux代码(当用户登录后,将获取到的颜色保存下来)
import Vue from "vue"
import {isHiddenPhone} from '@libs/http/vuex_http'

export let info = {
  namespaced:true,
  state:{
    skinName:'',
    _radio:null,  // '0':'1'
    timestamp:new Date().getTime() -0 + 1800000
  },
  getters: {
    radio: state => state.radio,
    getSkinName:state => state.skinName||'绀青',//默认皮肤
  },
  mutations: {
    changeSkin(state, data) {
      state.skinName = data
    },
    changeHiddenStatus(state, data) {
      state._radio = data
    },
  },
  actions: {
    actionSkinChange({ commit,getters},res){ // 修改state里面的skinName值
      commit('changeSkin',res)
    },
    httpForIsHiddenPhone ({ commit,getters}) {
      isHiddenPhone(Vue).then(res=>{
        if (res.data.code == '0') {
          //  是否隐藏  true 需要隐藏电话号码中间四位false 无需隐藏
          commit('changeHiddenStatus',res.data.data?'0':'1')
        }
      })
    }
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
4、切换主题色的关键代码
/**
		 * @description: 设置皮肤
		 * @param {themeName} 自定义的样式名称
		 * @return {*}
		 */
		setStyleRoot(themeName, themeList = []) {
			let arr = themeList.filter(q => q.themeName == themeName)
			if (arr.length == 0) return console.error('未设置样式皮肤')
			let item = arr[0]
			let root = []
			for (let i in item.style) {
				root.push(i + `:` + item.style[i])  
			}
			let test = `:root{${root.join(';')}}` // 拼接为样式代码, 
			// :root 这个 CSS 伪类匹配文档树的根元素。对于 HTML 来说,:root 表示 <html> 元素,除了优先级更高之外,与 html 选择器相同。
			this.addNode(test, item.src)
		},

		/**
		 * @description: 添加节点皮肤节点
		 * @param {test} 设置:root 样式
		 * @param {url} 插入的外链
		 * @return {*}
		 */
		addNode(test, url) {
			let styleNode = document.getElementById('theme')
			let linkNode = document.getElementById('linkTheme')
			if (styleNode) {     // 如果有节点就改变,没有就创建
				styleNode.innerHTML = test
				document.getElementsByTagName('body')[0].appendChild(styleNode)
				if(linkNode.getAttribute('href') != url) {
					linkNode.setAttribute('href', url)
				}
			} else {
				styleNode = document.createElement('style')
				linkNode = document.createElement('link')
				styleNode.setAttribute('id', 'theme')
				linkNode.setAttribute('href', url)
				linkNode.setAttribute('id', "linkTheme")
				linkNode.setAttribute('rel', "stylesheet")
				linkNode.setAttribute('type', "text/css")
				styleNode.innerHTML = test
				document.getElementsByTagName('body')[0].appendChild(styleNode)
				document.getElementsByTagName('head')[0].appendChild(linkNode)
			}
		},
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
5、less颜色变量代码
@primaryColor: var(--primary-color,#245BBF);  //主题色  var全局变量,--primary-color没有值的话,就是默认颜色#245BBF

//色值待替换    混合 白色百分比
@primaryColorMix05:var(--primary-mix05,#F3F6FC);
@primaryColorMix1:var(--primary-mix1,#E8EEF9);
@primaryColorMix2:var(--primary-mix2,#D3DEF2);
@primaryColorMix3:var(--primary-mix3,#BCCDEC);
@primaryColorMix4:var(--primary-mix4,#A7BDE5);
@primaryColorMix5:var(--primary-mix5,#91ACDF);
@primaryColorMix6:var(--primary-mix6,#7B9CDF);
@primaryColorMix7:var(--primary-mix7,#658BD2);
@primaryColorMix8:var(--primary-mix8,#4f7BCB);
@primaryColorMix9:var(--primary-mix9,#396BC5);


@borderColor_base: #e5e5e5;  //一般边框色值
@tableBColor_base:var(--table-header-bcolor,#F7F7F7);  //表格头部颜色

/* 导航栏色值 */
@navBackgroudColor: var(--nav-backgroud-color, #ffffff);
//@navBackgroudImg: var(--nav-backgroud-img);
@navUlBackgroudColor: var(--nav-ul-backgroud-color, #ffffff);
@navUlFontColor: var(--nav-ul-font-color, #ffffff);
@navUlActiveBackgroudColor: var(--nav-ul-active-backgroud-color, #ffffff);
@navUlActiveFontColor: var(--nav-ul-active-font-color, #ffffff);
@headerBackgroudColor: var(--header-backgroud-color, #ffffff);
//@headerBackgroudImg: var(--header-backgroud-img);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

ps:所有与主题颜色相关的color代码都要用@*****,例如某个css样式:

.active {
   font-size: 14px;
   font-weight: 700;
   color: @primaryColor;
   border-bottom: 1px solid @primaryColor;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
第三步:实现登录之后还原前一次保存的主题颜色
	  getSkin(){
        this.axios({
          url: "/service-user-app/app/user/config/select-by-userId",
          method: "get",
          interface:1
        }).then(res => {
          let data = res.data
          if (data.code == 0) {
            if(!data.data)return
            let obj = JSON.parse(data.data.val)
            this.actionSkinChange(obj.colour)//存起来
            this.setStyleRoot(obj.colour, themeList) //改变皮肤
          }
        })
      },
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

ps:接口返回:val: “{“platformSource”:22,“colour”:“绀青”}”,所以要反序列化一下。

年前分享一波,有能够优化的地方,还希望各位大佬指点指点。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/不正经/article/detail/84732
推荐阅读