给vue+element-ui动态设置主题色(包括外链样式、内联样式、行内样式)

前端开发 作者: 2024-08-20 21:25:01
基本思路 实现思路:实现一个mixins混入的主题js即theme.js,注册到全局下。使用el-color-picker组件切换颜色的时候,把颜色值传递到根root下,在根实例下监听主题色的变化来更
  • 1.把得到的主题色传递给根root实例,在根实例中监听主题色的变化,并调用setThemeColor(newval,oldval)方法;
  • 2.在APP.vue中监听路由变化,并调用《vue+element-ui动态设置主题效果》

    设置element-ui主题色引入到main.js中

    /* 改变主题色变量 */
    $--color-primary: #42b983;
    
     改变 icon 字体路径变量,必需 
    $--font-path: '~element-ui/lib/theme-chalk/fonts';
    
    @import "~element-ui/packages/theme-chalk/src/index";
    
    :export {
      colorPrimary: $--color-primary
    }
    import variables from '@/styles/element-variables.scss'

    全局混入theme.js、emitter.js

    • theme.js主要方法setThemeColor(newval,oldval),该方法传入新的颜色值与旧的颜色值;
    • emitter.js中使用$$dispatch方法把修改的主题色提交到根实例下;
    import theme from '@/mixins/theme.js'
    import emitter from '@/mixins/emitter.js'
    
    Vue.mixin(theme)
    Vue.mixin(emitter)

    核心代码调用

    • 主题色提交到根实例代码以及监听具体的路由页面修改样式(APP.vue)
    export default {
      name: 'App',inject: {
        themeConfig: {
          default: () => ({
            themeColor: ''
          })
        }
      },data() {
        return {
          themeColor: ''
        }
      },watch: {
        $route() {
          // 关键作用-进入到具体路由页面更新页面中DOM样式
          if (typeof this.themeConfig.themeColor != 'undefined' && this.themeConfig.themeColor !== this.themeConfig.defaultColor) {
            this.$nextTick(() => {
              this.themeConfig.themeColor && .themeConfig.defaultColor) {
                this.setThemeColor(this.themeConfig.themeColor,.themeConfig.defaultColor)
              }
            })
          }
        }
      },created() {
         如果本地存在主题色从本地获取,并提交给root分发到页面进行渲染
        if(Cookies.get('themeColor')) {
          this.themeColor = Cookies.get('themeColor');
          this.$$dispatch('root','root.config',[this.themeColor,1)">true]);  传递数组-解决初始加载执行setThemeColor两次问题
        } else {
          this.themeColor = .themeConfig.themeColor;
        }
      },methods: {
         改变主题颜色
        changeThemeColor(value) {
          'themeColor',value,{ path: '/' });
        }
      }
    }
    • 根实例监听获取的主题色并监听设置主题色(main.js)
    new Vue({
      el: '#app' {
          themeConfig:  {
          themeColor: variables.colorPrimary.toLowerCase(),defaultColor: variables.colorPrimary.toLowerCase(),themeFirstLoaded: true,1)"> 主题是否第一次加载,解决初始主题watch跟$route执行setThemeColor两次问题
        }
      },1)">this.$on('root.config',(result,themeFirstLoaded) =>this.themeColor = result.toLowerCase();
          this.themeFirstLoaded = themeFirstLoaded;
        })
      },watch: {
        themeColor(newval,oldval) {
          if(!.themeFirstLoaded) {
            .setThemeColor(newval,oldval);
          }
        }
      },router,components: { App },template: '<App/>'
    })

    theme.js设置主题代码

    export  {
      methods: {
         样式更新
        updateStyle(stylecon,oldCulster,newCluster) {
          let newStyleCon = stylecon;
          oldCulster.forEach((color,index) => {
            let regexp = '';
            if (color.split(',').length > 1) {
              const rgbArr = color.split(',');
              regexp = new RegExp("\\s*" + rgbArr[0] + "\\s*,\\s*" + rgbArr[1] + "\\s*,\\s*" + rgbArr[2] + "\\s*",'ig');
            }  {
              regexp = new RegExp(color,1)">);
            }
            newStyleCon = newStyleCon.replace(regexp,newCluster[index])
          })
           newStyleCon;
        }, 得到需要修改的一系类颜色值
        getThemeCluster(theme) {
          const clusters = [theme];
          for (let i = 0; i <= 9; i++) {
            clusters.push(this.getTintColor(theme,Number(i / 10).toFixed(2)));
          }
          clusters.push(this.getShadeColor(theme,0.1));
           clusters;
        },1)"> 得到色调颜色
        getTintColor(color,tint) {
          let red = parseInt(color.slice(0,2),16);
          let green = parseInt(color.slice(2,4),1)">);
          let blue = parseInt(color.slice(4,6),1)">);
    
          if (tint == 0) {
            return [red,green,blue].join(',1)">);
          }  {
            red += Math.round((255 - red) * tint);
            green += Math.round((255 - green) * tint);
            blue += Math.round((255 - blue) * tint);
            red = red.toString(16);
            green = green.toString(16);
            blue = blue.toString(16);
             `#${red}${green}${blue}`
          }
        },1)"> 获取阴影色调颜色
        getShadeColor(color,shade) {
          let red = parseInt(color.slice(0,1)">);
    
          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 `#${red}${green}${blue}`
        },1)"> 获取外链css文本内容
        getCSSText(url) {
          return new Promise((resolve,reject) => {
            const xhr =  XMLHttpRequest()
            xhr.onreadystatechange = () =>if (xhr.readyState === 4 && xhr.status === 200) {
                const styleText = xhr.responseText.replace(/@font-face{[^}]+}/,'')
                resolve(styleText);
              }
            }
            xhr.open('GET' 获取外链CSS样式的url地址
        getRequestUrl: function(src) {
          if (/^(http|https):\/\//g.test(src)) {
             src;
          }
          let filePath = .getFilePath();
          let count = 0;
          const regexp = /\.\.\//g;
          while (regexp.exec(src)) {
            count++;
          }
          while (count--) {
            filePath = filePath.substring(0,filePath.lastIndexOf('/'));
          }
          return filePath + "/" + src.replace(/\.\.\//g,"");
        },1)"> 获取当前window的url地址
        getFilePath: () {
          const curHref = window.location.href;
          if (curHref.indexOf('/#/') != -1return curHref.substring(0,curHref.indexOf('/#/'));
          }  {
            );
          }
        },1)"> 修改主题色-head样式以及DOM行内样式
        async setThemeColor(newval,1)">typeof newval !== 'string') ;
          const newThemeCluster = this.getThemeCluster(newval.replace('#',1)">));
          const orignalCluster = this.getThemeCluster(oldval.replace('#',1)"> 获取原始值中包含rgb格式的值存为数组
          const rgbArr = orignalCluster[1].split(',1)">);
          const orignalRGBRegExp = new RegExp("\\(\\s*" + rgbArr[0] + "\\s*,\\s*" + rgbArr[2] +
            "\\s*\\)",'i' 获取外链的样式内容并替换样式
          let styleTag = document.getElementById('new-configTheme__styles');
          const tagsDom = document.getElementsByTagName('link'if (!styleTag && tagsDom.length) {
            styleTag = document.createElement('style')
            styleTag.setAttribute('id','new-configTheme__styles')
            document.head.appendChild(styleTag);
            const tagsDomList = Array.prototype.slice.call(tagsDom);
            let innerTextCon = ''for (let i = 0; i < tagsDomList.length; i++) {
              const value = tagsDomList[i];
              const tagAttributeSrc = value.getAttribute('href');
              const requestUrl = .getRequestUrl(tagAttributeSrc);
              const styleCon = await .getCSSText(requestUrl);
              new RegExp(oldval,'i').test(styleCon) || orignalRGBRegExp.test(styleCon)) {
                innerTextCon += .updateStyle(styleCon,orignalCluster,newThemeCluster);
              }
            }
            styleTag.innerText = innerTextCon;
          }
    
           获取页面的style标签
          const styles = [].slice.call(document.querySelectorAll('style')).filter((style) => {
            const text = style.innerText;
             orignalRGBRegExp.test(text);
          })
    
           获取页面的style标签内容,使用updateStyle直接更新即可
          styles.forEach((style) => {
            const {
              innerText
            } = style;
            typeof innerText !== 'string') ;
            style.innerText = .updateStyle(innerText,newThemeCluster);
          })
    
           获取DOM元素上的style
          const domAll = [].slice.call(document.getElementsByTagName('*')).filter((dom,index) => {
            const stylCon = dom.getAttribute('style'return stylCon && ( orignalRGBRegExp.test(stylCon))
          })
          domAll.forEach((dom) => {
            const styleCon = dom.getAttribute('style');
            dom.style = 
    
    const ExtractTextPlugin = require('extract-text-webpack-plugin')  提取CSS
    const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')  压缩CSS
    
    const devWebpackConfig = merge(baseWebpackConfig,{
      module: {
        rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap,extract: true })
      },plugins: [
         ...省略其他代码
         ExtractTextPlugin({
          filename: 'bundle.css'
        }),1)"> OptimizeCSSPlugin({
          cssProcessorOptions: config.build.productionSourceMap
            ? { safe: false } }
            : { safe:  }
        })
      ]
    })
原创声明
本站部分文章基于互联网的整理,我们会把真正“有用/优质”的文章整理提供给各位开发者。本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
本文链接:http://www.jiecseo.com/news/show_65727.html