Vue 换肤的示例实践


Posted in Javascript onJanuary 23, 2018

最近公司做的项目得到一个网站换肤的需求,也就是切换主题。那么如何切换主题色呢?切换主题色其实就是切换 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,如果有更好的方法,欢迎与我交流。

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

Javascript 相关文章推荐
一些javascript一些题目的解析
Dec 25 Javascript
JavaScript中使用Substring删除字符串最后一个字符
Nov 03 Javascript
解决用jquery load加载页面到div时,不执行页面js的问题
Feb 22 Javascript
js实现checkbox全选和反选示例
May 01 Javascript
jQuery简单实现仿京东分类导航层效果
Jun 07 Javascript
JS实现简易的图片拖拽排序实例代码
Jun 09 Javascript
Angular动态绑定样式及改变UI框架样式的方法小结
Sep 03 Javascript
vue+axios+element ui 实现全局loading加载示例
Sep 11 Javascript
用vue-cli开发vue时的代理设置方法
Sep 20 Javascript
浅谈让你的代码更简短,更整洁,更易读的ES6小技巧
Oct 25 Javascript
vue将后台数据时间戳转换成日期格式
Jul 31 Javascript
Vue基于iview table展示图片实现点击放大
Aug 05 Javascript
js和jQuery以及easyui实现对下拉框的指定赋值方法
Jan 23 #jQuery
Vue 拦截器对token过期处理方法
Jan 23 #Javascript
浅谈React + Webpack 构建打包优化
Jan 23 #Javascript
vue组件编写之todolist组件实例详解
Jan 22 #Javascript
基于openlayers4实现点的扩散效果
Aug 17 #Javascript
vue-cli启动本地服务局域网不能访问的原因分析
Jan 22 #Javascript
webpack引入eslint配置详解
Jan 22 #Javascript
You might like
php 动态多文件上传
2009/01/18 PHP
提高PHP编程效率的53个要点(经验小结)
2010/09/04 PHP
PHP学习笔记 (1) 环境配置与代码调试
2011/06/19 PHP
基于Zend的Config机制的应用分析
2013/05/02 PHP
php递归函数三种实现方法及如何实现数字累加
2015/08/07 PHP
基础的WordPress插件制作教程
2015/11/24 PHP
使用jQuery.Validate进行客户端验证(初级篇) 不使用微软验证控件的理由
2010/06/28 Javascript
jQuery ajax在GBK编码下表单提交终极解决方案(非二次编码方法)
2010/10/20 Javascript
Bootstrap每天必学之滚动监听
2016/03/16 Javascript
js点击返回跳转到指定页面实现过程
2020/08/20 Javascript
JavaScript 总结几个提高性能知识点(推荐)
2017/02/20 Javascript
jQuery输入框密码的显示隐藏【代码分享】
2017/04/29 jQuery
详解vue中computed 和 watch的异同
2017/06/30 Javascript
浅谈Vue响应式(数组变异方法)
2018/05/07 Javascript
Webpack 4.x搭建react开发环境的方法步骤
2018/08/15 Javascript
vue配置font-awesome5的方法步骤
2019/01/27 Javascript
详解几十行代码实现一个vue的状态管理
2019/01/28 Javascript
微信小程序保存图片到相册权限设置
2020/04/09 Javascript
vue中实现拖动调整左右两侧div的宽度的示例代码
2020/07/22 Javascript
python基础教程之自定义函数介绍
2014/08/29 Python
Python操作MongoDB详解及实例
2017/05/18 Python
TensorFlow安装及jupyter notebook配置方法
2017/09/08 Python
pyqt5简介及安装方法介绍
2018/01/31 Python
10行Python代码计算汽车数量的实现方法
2019/10/23 Python
使用pandas的box_plot去除异常值
2019/12/10 Python
python如何实现单链表的反转
2020/02/10 Python
Django Admin设置应用程序及模型顺序方法详解
2020/04/01 Python
python批量生成身份证号到Excel的两种方法实例
2021/01/14 Python
django inspectdb 操作已有数据库数据的使用步骤
2021/02/07 Python
Nanushka官网:匈牙利服装品牌
2019/08/14 全球购物
英国电气世界:Electrical World
2019/09/08 全球购物
UNIX命令速查表
2012/03/10 面试题
《会变的花树叶》教学反思
2014/02/10 职场文书
apache基于端口创建虚拟主机的示例
2021/04/22 Servers
win10+anaconda安装yolov5的方法及问题解决方案
2021/04/29 Python
星际争霸 Light vs Action 一场把教主看到鬼畜的比赛
2022/04/01 星际争霸