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 的方法重载效果
Aug 07 Javascript
yepnope.js 异步加载资源文件
Sep 08 Javascript
如何在JavaScript中实现私有属性的写类方式(二)
Dec 04 Javascript
教你如何使用firebug调试功能了解javascript闭包和this
Mar 04 Javascript
js如何判断访问是来自搜索引擎(蜘蛛人)还是直接访问
Sep 14 Javascript
对比分析Django的Q查询及AngularJS的Datatables分页插件
Feb 07 Javascript
JavaScript数据结构之二叉树的遍历算法示例
Apr 13 Javascript
layui弹出层效果实现代码
May 19 Javascript
Vue用v-for给src属性赋值的方法
Mar 03 Javascript
React Native日期时间选择组件的示例代码
Apr 27 Javascript
总结4个方面优化Vue项目
Feb 11 Javascript
JavaScript 接口原理与用法实例详解
May 12 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
全国FM电台频率大全 - 30 宁夏回族自治区
2020/03/11 无线电
php快速url重写更新版[需php 5.30以上]
2010/04/25 PHP
php生成图形(Libchart)实例
2013/11/06 PHP
php之Smarty模板使用方法示例详解
2014/07/08 PHP
ThinkPHP文件缓存类代码分享
2015/04/22 PHP
php实现文本数据导入SQL SERVER
2015/05/17 PHP
Ubuntu下安装PHP的mongodb扩展操作命令
2015/07/04 PHP
jQuery 标题的自动翻转实现代码
2009/10/14 Javascript
异步javascript的原理和实现技巧介绍
2012/11/08 Javascript
jquery 列表双向选择器之改进版
2013/08/09 Javascript
js动态添加删除,后台取数据(示例代码)
2013/11/25 Javascript
jQuery实现复选框全选/取消全选/反选及获得选择的值
2014/06/12 Javascript
基于JavaScript制作霓虹灯文字 代码 特效
2015/09/01 Javascript
javascript对象的相关操作小结
2016/05/16 Javascript
jQuery模拟select实现下拉菜单功能
2016/06/20 Javascript
JavaScript实现相册弹窗功能(zepto.js)
2016/06/21 Javascript
JavaScript循环_动力节点Java学院整理
2017/06/28 Javascript
js+html获取系统当前时间
2017/11/10 Javascript
解决Nodejs全局安装模块后找不到命令的问题
2018/05/15 NodeJs
微信小程序音乐播放器开发
2019/11/20 Javascript
js实现带有动画的返回顶部
2020/08/09 Javascript
[03:47]2015国际邀请赛第三日现场精彩回顾
2015/08/08 DOTA
使用Pyrex来扩展和加速Python程序的教程
2015/04/13 Python
python爬取拉勾网职位数据的方法
2018/01/24 Python
对python中基于tcp协议的通信(数据传输)实例讲解
2019/07/22 Python
python判断变量是否为列表的方法
2020/09/17 Python
浅析python实现动态规划背包问题
2020/12/31 Python
HTML5组件Canvas实现图像灰度化(步骤+实例效果)
2013/04/22 HTML / CSS
ALLSAINTS英国官网:伦敦新锐潮流品牌
2016/09/19 全球购物
DJI全球:DJI Global
2021/03/15 全球购物
介绍一下linux文件系统分配策略
2012/11/17 面试题
校园报刊亭创业计划书
2014/01/02 职场文书
运动会开幕式解说词
2014/02/05 职场文书
保护环境倡议书范文
2014/05/13 职场文书
学校领导班子成员查摆问题及整改措施
2014/10/28 职场文书
浅谈Python列表嵌套字典转化的问题
2021/04/07 Python