Example code for implementing dynamic skinning with vue+element

Example code for implementing dynamic skinning with vue+element

Sometimes the theme of a project cannot satisfy everyone's aesthetics. At this time, the skin-changing function is very friendly. This project implements the skin-changing function of the background management project based on vue+element

1. Create a skinning component

<template>
  <el-color-picker
    class="theme-picker"
    popper-class="theme-picker-dropdown"
    v-model="theme"
    :predefine="predefineColors"
  ></el-color-picker>
</template>
 
<script>
const version = require("element-ui/package.json").version; // element-ui version from node_modules
const ORIGINAL_THEME = "#409EFF"; // default color
export default {
  name: "ThemePicker",
  props: {
    default: {
      // Initialize the topic, which can be passed in from outside type: String
      // default: '#2668b1'
      // default: `${localStorage.getItem("tremePackers")==null?"#C60404":localStorage.getItem("tremePackers")}`
    }
    // size: { // Initialize the topic, which can be passed in from outside // type: String,
    // default: 'small'
    // },
  },
  data() {
    return {
      chalk: "", // content of theme-chalk css
      theme: ORIGINAL_THEME,
      showSuccess: true, // Whether to pop up the skin change success message predefineColors: [
        "#2668b1",
        "#52b493",
        "#429798",
        "#32789c",
        "#1944a5",
        "#5944bc",
        "#995dcd",
        "#ce7e5b",
        "#ee8b9b",
        "#283551"
      ]
    };
  },
  mounted() {
    this.theme = this.defaultTheme;
    // this.$emit('onThemeChange', this.theme)
    this.showSuccess = true;
  },
  computed: {
    defaultTheme() {
      return this.$store.state.theme;
    }
  },
  watch:
    async theme(val, oldVal) {
          if (typeof val !== "string") return;
          const themeCluster = this.getThemeCluster(val.replace("#", ""));
          const originalCluster = this.getThemeCluster(oldVal.replace("#", ""));
          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)
                document
                  .getElementsByTagName("style")[0]
                  .insertBefore(styleTag, null);
              }
              styleTag.innerText = newStyle;
            };
          };
 
          const chalkHandler = getHandler("chalk", "chalk-style");
 
          if (!this.chalk) {
            const url = `../../assets/style/theme/index.css`; //Local CSS style address // const url = `./dist/index.css`; //CSS address after project packaging (the original file is placed in the public folder)
            // const url = `https://unpkg.com/element-ui@${version}/lib/theme-chalk/index.css`; //If it is a company intranet, this URL is not applicable 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.$store.commit("themColor", val);//Save the changed color to the store
          this.$emit("onThemeChange", val);
 
        // Respond to external operations // Store in localStorage
        // localStorage.setItem('tremePackers',val);
        // if(this.showSuccess) {
        // this.$message({
        // message: 'Skin change successful',
        // type: 'success'
        // })
        // } else {
        // this.showSuccess = true
        // }
      
    }
  },
  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) => {
        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;
    }
  }
};
</script>
 
<style>
.theme-picker .el-color-picker__trigger {
  vertical-align: middle;
}
 
.theme-picker-dropdown .el-color-dropdown__link-btn {
  display: none;
}
.el-color-picker--small .el-color-picker__trigger {
  border: none;
}
</style> 

The code above is worth noting. The code in the red box inserts a new style tag after all nodes in the head. After packaging, it has a higher priority, but there is a problem. The color of some places disappears directly and becomes blank, affecting the style. So it is changed to the code in the green box. However, the priority of the code in the green box will be lower than the priority of the original style color after packaging, so the style priority needs to be adjusted according to the project.

This code also needs attention. If the company directly uses the external network, then you can directly use the third URL. If the company uses the internal network that cannot access external web pages, you can download the css style of the element version of the project through the third URL and put the css file in the project, but be careful to put it in the folder that will not be compiled. My project uses vue cli4, so the css file I dynamically converted is placed in the public folder. The style file in the assets folder will be compiled, so the path will report 404, and the url used in this block is the path of the style after the file is packaged and compiled. This is worth noting.

2. If some style colors in the project do not use element, you can cache the color in vuex, and then obtain it through calculated properties in the specific step and then dynamically bind it to the style

vuex:

Components used:

This concludes this article about the sample code for implementing dynamic skin changing with vue+element. For more relevant vue+element dynamic skin changing content, please search for previous articles on 123WORDPRESS.COM or continue to browse the following related articles. I hope you will support 123WORDPRESS.COM in the future!

You may also be interested in:
  • Integration practice of Vue+Element background management framework
  • Use Element+vue to implement start and end time limits
  • Antdesign-vue combined with sortablejs to achieve the function of dragging and sorting two tables
  • Detailed explanation of dragging table columns using Vue Element Sortablejs

<<:  Docker+K8S cluster environment construction and distributed application deployment

>>:  VS2019 connects to mysql8.0 database tutorial with pictures and text

Recommend

MySQL msi installation tutorial under windows10 with pictures and text

1. Download 1. Click the latest download from the...

How to install mysql database in deepin 2014 system

Deepin 2014 download and installation For downloa...

Analysis of several situations where MySQL index fails

1. Best left prefix principle - If multiple colum...

Advanced crawler - Use of Scrapy_splash component for JS automatic rendering

Table of contents 1. What is scrapy_splash? 2. Th...

Tutorial on installing and configuring remote login to MySQL under Ubuntu

This article shares the MySQL installation and co...

How to start and restart nginx in Linux

Nginx (engine x) is a high-performance HTTP and r...

Details of function nesting and closures in js

Table of contents 1. Scope 2. Function return val...

Detailed explanation of MySQL group sorting to find the top N

MySQL group sorting to find the top N Table Struc...

How to solve the margin collapse problem in CSS

First, let's look at three situations where m...

Optimizing JavaScript and CSS to improve website performance

<br /> In the first and second parts, we int...

Introduction to the use of anchors (named anchors) in HTML web pages

The following information is compiled from the Int...

JavaScript to achieve simple drag effect

This article shares the specific code of JavaScri...

About WSL configuration and modification issues in Docker

https://docs.microsoft.com/en-us/windows/wsl/wsl-...