欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Vue 换肤的示例实践

程序员文章站 2022-04-10 11:09:35
最近公司做的项目得到一个网站换肤的需求,也就是切换主题。那么如何切换主题色呢?切换主题色其实就是切换 css,然而在项目中不仅只有 css 需要换肤,图标和图片也需要跟随主...

最近公司做的项目得到一个网站换肤的需求,也就是切换主题。那么如何切换主题色呢?切换主题色其实就是切换 css,然而在项目中不仅只有 css 需要换肤,图标和图片也需要跟随主题进行切换。于是,写一篇文章来记录下 vue 中实现换肤的过程,先看下效果吧。

Vue 换肤的示例实践

本文主要分三部分:css 切换,图标切换和图片切换。

css切换

关于 css 颜色的切换,我通过搜索,参考了elementui 的方案,总的来说分为四步

在 static 目录下新建一个 theme.css 文件,将需要替换的 css 声明在此文件中

.side-bar {
 background: linear-gradient(#b7a3ff, #879fff) !important;
}

.side-bar .account-info {
 background: #8981d8 !important;
}

声明所有可选的主题,每种颜色都对应于一个关键词,方便区分

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'
}]

通过 ajax 获取 theme.css ,将颜色值替换为关键词。

 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
}

把关键词再换回刚刚生成的相应的颜色值,并在页面上添加 style 标签

 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)
}

图标切换

由于项目刚开始做的时候并没有考虑到换肤的需求,于是所有图标都是采用 img 标签的方式引用的,

 <img src="../../assets/icon_edit.svg">

这样就导致无法给 icon 动态切换颜色了,所以,我决定改为 font 文件的方式来使用图标。这里推荐一个网站 icomoon ,这个网站可以轻松地将图片转换成 font 文件。图标也非常适合通过 font 的方式来使用,我们可以更加方便的修改图标的大小和颜色。

通过在线转换,我们将下载下来的 font 文件放入项目中,并新建一个 css 文件来声明所有图标。

@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";
}

之后就能通过 css 类名的方式来引用图标了。

 <span class="icon-edit"></span>

为了使主题生效,我们也需要把图标的 css 写入 theme.css 文件中

.icon_edit:before {
 background-image: linear-gradient(-135deg, #879fff 0%, #b7a3ff 100%);
}

图片切换

项目中还存在很多占位图或者其他图片会随着主题的变化而变化。通过引入所有图片,并用文件名来区分不同主题所对应的图片。在点击切换主题时,切换到主题所对应的文件,就能实现图片切换了。为此,我写了一个 mixin,并在组件中引入 mixin。

<img :src="userimg || placeholderwoman">

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`)
  }
 }
}

在点击切换主题时,会发射一个 changetheme 事件,各组件接收到 changetheme 事件,就会为图片重新赋值,也就达到了切换图片的效果。

let theme = themeid2name(this.themeid)
bus.$emit('changetheme', theme)

这样也就达到了切换主题的效果,但是这种方法需要在几乎所有业务组件中引入 mixin,如果有更好的方法,欢迎与我交流。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。