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 相关文章推荐
JavaScipt基本教程之前言
Jan 16 Javascript
用Javascript 获取页面元素的位置的代码
Sep 25 Javascript
通过Jquery遍历Json的两种数据结构的实现代码
Jan 19 Javascript
Javascript 拖拽的一些高级的应用(逐行分析代码,让你轻松了拖拽的原理)
Jan 23 Javascript
Node.js 学习笔记之简介、安装及配置
Mar 03 Javascript
javascript this详细介绍
Sep 19 Javascript
学习vue.js计算属性
Dec 03 Javascript
详解JavaScript常量定义
Jan 03 Javascript
Javascript基础回顾之(三) js面向对象
Jan 31 Javascript
AngularJS ng-repeat指令及Ajax的应用实例分析
Jul 06 Javascript
JavaScript实现各种排序的代码详解
Aug 28 Javascript
js实现无刷新监听URL的变化示例代码详解
Jun 03 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
如何将数据从文本导入到mysql
2006/10/09 PHP
PHP 加密/解密函数 dencrypt(动态密文,带压缩功能,支持中文)
2009/01/30 PHP
PHP 如何获取二维数组中某个key的集合
2014/06/03 PHP
举例详解PHP脚本的测试方法
2015/08/05 PHP
php实现简单爬虫的开发
2016/03/28 PHP
PHP内置加密函数详解
2016/11/20 PHP
JavaScript Prototype对象
2009/01/07 Javascript
在多个页面使用同一个HTML片段《续》
2011/03/04 Javascript
html中的input标签的checked属性jquery判断代码
2012/09/19 Javascript
JavaScript中“+”的陷阱深刻理解
2012/12/04 Javascript
图标线性回归斜着移动到指定的位置
2013/08/16 Javascript
jquery $.each() 使用小探
2013/08/23 Javascript
jQery使网页在显示器上居中显示适用于任何分辨率
2014/06/09 Javascript
基于JavaScript实现一定时间后去执行一个函数
2015/12/14 Javascript
AngularJS入门示例之Hello World详解
2017/01/04 Javascript
jQuery的$.extend 浅拷贝与深拷贝
2017/03/08 Javascript
基于vue2.0动态组件及render详解
2018/03/17 Javascript
详解基于webpack&amp;gettext的前端多语言方案
2019/01/29 Javascript
layUI实现前端分页和后端分页
2019/07/27 Javascript
vue点击Dashboard不同内容 跳转到同一表格的实例
2020/11/13 Javascript
Python3爬楼梯算法示例
2019/03/04 Python
2020新版本pycharm+anaconda+opencv+pyqt环境配置学习笔记,亲测可用
2020/03/24 Python
基于Python把网站域名解析成ip地址
2020/05/25 Python
Python3.8安装Pygame教程步骤详解
2020/08/14 Python
美国最顶级的精品店之一:Hampden Clothing
2016/12/22 全球购物
美国最大的网上冲印店:Shutterfly
2017/01/01 全球购物
四川成都导游欢迎词
2014/01/18 职场文书
基层干部十八大感言
2014/01/19 职场文书
小学教师节活动方案
2014/01/31 职场文书
简单的个人租房协议书范本
2014/11/26 职场文书
2015年党性分析材料
2014/12/19 职场文书
傲慢与偏见读书笔记
2015/06/29 职场文书
2016年中秋节慰问信
2015/12/01 职场文书
2016暑期政治学习心得体会
2016/01/23 职场文书
关于React Native使用axios进行网络请求的方法
2021/08/02 Javascript
Python基本知识点总结
2022/04/07 Python