Original Vue skin changing practice

A recent company project received a request for a website skin change, that is, to switch themes. So how to switch theme colors? Switching the theme color is essentially switching the CSS, but it’s not just the CSS that needs to be skinned in a project, ICONS and images also need to be switched with the theme. So, write an article to document the process of implementing skin change in Vue, and see the effect first.

This paper is divided into three parts: CSS switching, icon switching and image switching.

CSS switch

In terms of CSS color switching, I refer to ElementUI’s scheme through search, which is generally divided into four steps

  • Create a new one in the static directorytheme.cssFile that will need to replace the CSS declaration in this file
.side-bar { background: linear-gradient(#B7A3FF, #879FFF) ! important; } .side-bar .account-info { background: #8981D8 ! important; }Copy the code
  • Declare all optional themes, each color corresponding to a keyword, easy to distinguish
colors: [{
  themeId: 1,
  familyPrimary: '#B7A3FF',
  familySecondary: '#879FFF',
  sideBarTop: '#8981D8'
}, {
  themeId: 2,
  familyPrimary: '#FDC5C5',
  familySecondary: '#F070A0',
  sideBarTop: '#E7829F'
}, {
  themeId: 3,
  familyPrimary: '#414D6C',
  familySecondary: '#2D1E3C',
  sideBarTop: '#423C50'
}]Copy the code
  • Get via AJAXtheme.css, replace the color value with the keyword.
 getFile(`/static/theme.css`)
   .then(({data}) => {
      let style = getStyleTemplate(data)
   })

function getStyleTemplate (data) {
  const colorMap = {
    '#B7A3FF': 'familyPrimary',
    '#879FFF': 'familySecondary',
    '#8981D8': 'sideBarTop'
  }
  Object.keys(colorMap).forEach(key => {
    const value = colorMap[key]
    data = data.replace(new RegExp(key, 'ig'), value)
  })
  return data
}Copy the code
  • Replace the keyword with the corresponding color value you just generated and add it to the pagestyleThe label
 getFile(`/static/theme.css`)
   .then(({data}) => {
      let style = getStyleTemplate(data)
      writeNewStyle(style, this.color)
   })

function writeNewStyle (originalStyle, colors) {
  let oldEl = document.getElementById('temp-style')
  let cssText = originalStyle
  Object.keys(colors).forEach(key => {
    cssText = cssText.replace(new RegExp(key, 'ig'), colors[key])
  })
  const style = document.createElement('style')
  style.innerText = cssText
  style.id = 'temp-style'
  oldEl ? document.head.replaceChild(style, oldEl) : document.head.appendChild(style)
}Copy the code

ICONS switching

Since we didn’t consider the need for skin changes when we started the project, all ICONS were referenced in the way of IMG tags,

<img src=".. /.. /assets/icon_edit.svg">Copy the code

This made it impossible to dynamically switch colors on the icon, so I decided to use the icon as a font file instead. I recommend icomoon, a site that makes it easy to convert images to font files. Font is also a great way to change the size and color of ICONS.

Using an online conversion, we put the font file we downloaded into the project and create a new CSS file to declare all ICONS.

@font-face { font-family: 'icomoon'; src: url('.. /assets/fonts/icomoon.eot? vpkwno'); src: url('.. /assets/fonts/icomoon.eot? vpkwno#iefix') format('embedded-opentype'), url('.. /assets/fonts/icomoon.ttf? vpkwno') format('truetype'), url('.. /assets/fonts/icomoon.woff? vpkwno') format('woff'), url('.. /assets/fonts/icomoon.svg? vpkwno#icomoon') format('svg'); font-weight: normal; font-style: normal; } [class^="icon-"], [class*=" icon-"] { /* use ! important to prevent issues with browser extensions that change fonts */ font-family: 'icomoon' ! important; speak: none; font-style: normal; font-weight: normal; font-variant: normal; text-transform: none; line-height: 1; vertical-align: sub; /* Better Font Rendering =========== */ -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } .icon-edit:before { content: "\e900"; }Copy the code

You can then refer to the icon by CSS class name.

 <span class="icon-edit"></span>Copy the code

For the theme to work, we also need to write the icon’s CSS to the theme.css file

.icon_edit:before {
  background-image: linear-gradient(-135deg, #879FFF 0%, #B7A3FF 100%);
}Copy the code

Image switching

There are also lots of placeholders and other images that change from theme to theme. By introducing all images and using file names to distinguish the images that correspond to different themes. Click on the switch theme, switch to the theme of the corresponding file, you can realize the picture switch. To do this, I write a mixin and introduce mixins into the component.

<img :src="userImg || placeholderWoman">Copy the code

placeholderMixin

let callback const placeholderMixin = { data () { return { placeholderWoman: '', placeHolderNoReply: '', placeHolderNothing: "'}}, created () { let themeId = localStorage.getItem('themeId') let theme = themeId2Name(themeId) this.setThemeValue(theme) callback = (theme) => { this.setThemeValue(theme) } bus.$on('changeTheme', callback) }, destroyed () { bus.$off('changeTheme', callback) }, methods: { setThemeValue (theme) { this.placeholderWoman = require(`@/assets/placeholder_woman_${theme}.svg`) this.placeHolderNoReply = require(`@/assets/icon_noreply_${theme}.svg`) this.placeHolderNothing = require(`@/assets/icon_nothing_${theme}.svg`) } } }Copy the code

When you click to switch the theme, a changeTheme event will be emitted. Each component receives the changeTheme event and will reassign the value to the image, thus achieving the effect of switching the image.

let theme = themeId2Name(this.themeId)
bus.$emit('changeTheme', theme)Copy the code

This works as well as switching themes, but this approach requires introducing mixins into almost all business components, so let me know if there’s a better way.