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 实现模态对话框 源代码大全
May 02 Javascript
用Mootools获得操作索引的两种方法分享
Dec 12 Javascript
JS实现的仿东京商城菜单、仿Win右键菜单及仿淘宝TAB特效合集
Sep 28 Javascript
jquery计算出left和top,让一个div水平垂直居中的简单实例
Jul 13 Javascript
深入浅析JS是按值传递还是按引用传递(推荐)
Sep 18 Javascript
Node.js测试中的Mock文件系统详解
Nov 21 Javascript
JS实现的简单图片切换功能示例【测试可用】
Feb 14 Javascript
微信小程序 常用工具类详解及实例
Feb 15 Javascript
jQuery查找dom的几种方法效率详解
May 17 jQuery
详解开源的JavaScript插件化框架MinimaJS
Oct 26 Javascript
深入浅析JSONAPI在PHP中的应用
Dec 24 Javascript
Angular开发实践之服务端渲染
Mar 29 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简洁函数(PHP简单明了函数语法)
2012/06/10 PHP
php自动识别文字编码并转换为目标编码的方法
2015/08/08 PHP
php中类和对象:静态属性、静态方法
2017/04/09 PHP
JavaScript 获得选中文本内容的方法
2009/02/15 Javascript
javascript 混合的构造函数和原型方式,动态原型方式
2009/12/07 Javascript
ExtJs 表单提交登陆实现代码
2010/08/19 Javascript
Ionic实现仿通讯录点击滑动及$ionicscrolldelegate使用分析
2016/01/18 Javascript
AngularJS中关于ng-class指令的几种实现方式详解
2016/09/17 Javascript
Angular2 (RC4) 路由与导航详解
2016/09/21 Javascript
Node.js与MySQL交互操作及其注意事项
2016/10/05 Javascript
关于JavaScript中事件绑定的方法总结
2016/10/26 Javascript
原生JS简单实现ajax的方法示例
2016/11/29 Javascript
输入框点击时边框变色效果的实现方法
2016/12/26 Javascript
vue中实现图片和文件上传的示例代码
2018/03/16 Javascript
微信小程序中使用自定义图标(阿里icon)的方法
2018/08/20 Javascript
详解Webpack-dev-server的proxy用法
2018/09/08 Javascript
javascript实现5秒倒计时并跳转功能
2019/06/20 Javascript
layui表格数据重载
2019/07/27 Javascript
vue框架制作购物车小球动画效果实例代码
2019/09/26 Javascript
JavaScript中的this原理及6种常见使用场景详解
2020/02/14 Javascript
解析Python中的__getitem__专有方法
2016/06/27 Python
在python中利用pycharm自定义代码块教程(三步搞定)
2020/04/15 Python
Python3内置函数chr和ord实现进制转换
2020/06/05 Python
浅谈matplotlib中FigureCanvasXAgg的用法
2020/06/16 Python
python如何导出微信公众号文章方法详解
2020/08/31 Python
css3 实现圆形旋转倒计时
2018/02/24 HTML / CSS
用HTML5中的Canvas结合公式绘制粒子运动的教程
2015/05/08 HTML / CSS
浅谈html5 video 移动端填坑记
2018/01/15 HTML / CSS
Engel & Bengel官网:婴儿推车、儿童房家具和婴儿设备
2019/12/28 全球购物
大学生护理专业自荐信
2013/10/03 职场文书
学校督导评估方案
2014/06/10 职场文书
小学领导班子对照材料
2014/08/23 职场文书
单位委托书格式范本
2014/09/29 职场文书
离婚协议书标准格式
2014/10/04 职场文书
2015年大学社团工作总结
2015/04/09 职场文书
Pytorch 使用tensor特定条件判断索引
2021/04/08 Python