详解Vue 换肤方案验证


Posted in Javascript onAugust 28, 2019

本文的换肤方案灵感来自于 element-ui

需求:网站换肤,主题切换。网站的主题色可以在几种常用颜色之间进行切换,还有相关图片、图标也要跟随主题进行切换。

不多说,先看下最终的实现效果:

详解Vue 换肤方案验证

文章由两部分组成:css切换,图片图标切换

css切换

1.在 static 目录下新建一个 styles 文件夹,在 styles 下新建一个 theme.scss 文件(项目使用了sass,会自动编译成css文件,如果没有使用这些预处理工具可以直接新建 theme.css),将需要替换的 CSS 声明在此文件中。

.theme-test-btn {
  background-color: #409eff;
  border-color: #409eff;
}

.theme-test-btn:hover,
.theme-test-btn:focus {
  background-color: #66b1ff;
  border-color: #66b1ff;
}

2.在 src/assets/js/const/ 目录下新建 theme-colors.js,用于声明所有可选的主题,每种颜色都对应一个关键词,方便区分

const colors = [
  {
    themeId: 0,
    primaryBtn: '#409eff', // 主要按钮的背景色
    priBtnHover: '#66b1ff', // 主要按钮的悬浮、聚焦背景色
  },
  {
    themeId: 1,
    primaryBtn: '#67c23a',
    priBtnHover: '#85ce61',
  },
  {
    themeId: 2,
    primaryBtn: '#e6a23c',
    priBtnHover: '#ebb563',
  },
];

export default colors;

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

data() {
  return {
    active: 0,
    themeStyleStr: '', // 存放 替换成关键词的 theme.css 内容
    colors: themeColors, // 所有可选的主题颜色数组。即:theme-colors.js 文件export的数组
  };
},
mounted() {
  // 通过 ajax 获取 theme.css 的内容,并将颜色值替换为关键词
  this.$http.getThemeFile().then(res => {
    this.themeStyleStr = this.getStyleTemplate(res);
  });
},
methods: {
  // 获取样式模板:将颜色值替换为关键词。
  getStyleTemplate(data) {
    let color = this.colors[0];
    delete color.themeId;
    let colorMap = {};
    Object.keys(color).forEach(key => {
      colorMap[color[key]] = key;
    });
    Object.keys(colorMap).forEach(key => {
      data = data.replace(new RegExp(key, 'ig'), colorMap[key]);
    });
    return data;
  },
}

this.$http.getThemeFile 方法

// 使用原生ajax获取换肤的样式文件
getThemeFile() {
  return new Promise(resolve => {
    const url = location.origin + '/static/styles/theme.css';
    const xhr = new XMLHttpRequest();
    xhr.onreadystatechange = () => {
      if (xhr.readyState === 4 && xhr.status === 200) {
        resolve(xhr.responseText);
      }
    };
    xhr.open('GET', url);
    xhr.send();
  });
}

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

methods: {
  // 点击切换主题
  changeTheme(index) {
    this.active = index;
    this.setNewStyle(this.themeStyleStr, this.colors[index]);
  },
  // 根据选择的主题颜色,把关键词换成相应的主题颜色,并在页面上添加 style 标签
  setNewStyle(originalStyle, colors) {
    let oldEl = document.getElementById('theme-style');
    let cssText = originalStyle;
    Object.keys(colors).forEach(key => {
      cssText = cssText.replace(new RegExp(key, 'ig'), colors[key]);
    });
    const style = document.createElement('style');
    style.innerHTML = cssText;
    style.id = 'theme-style';
    oldEl ? document.head.replaceChild(style, oldEl) : document.head.appendChild(style);
  }
}

图片图标切换

1.图片切换和图标切换是同样的原理。在之前新建好的 theme.scss 文件追加图标引入的样式。

.theme-test-icon {
  background: url("/static/images/common/list-modify-icon.svg");
}

2.在之前新建好的 theme-colors.js 文件追加图标路径

/*图片统一使用一个路径,更换主题时需要在images文件夹下新建主题文件夹,与原始路径对应,图片文件名须一致
应避免 primaryBtn 与 primaryBtnHover 同时出现,因为正则匹配 primaryBtn 会把 primaryBtnHover 部分匹配出来,达不到效果*/
const colors = [
  {
    themeId: 0,
    primaryBtn: '#409eff', // 主要按钮的背景色
    priBtnHover: '#66b1ff', // 主要按钮的悬浮、聚焦背景色
    imagePath: '/static/images', // 图片绝对路径
  },
  {
    themeId: 1,
    primaryBtn: '#67c23a',
    priBtnHover: '#85ce61',
    imagePath: '/static/images/theme1',
  },
  {
    themeId: 2,
    primaryBtn: '#e6a23c',
    priBtnHover: '#ebb563',
    imagePath: '/static/images/theme2',
  },
];
export default colors;

3.引入需要主题切换的图片/图标,存放于 /static/images/ 之下,每个额外的主题图片需要一个文件夹进行存放,例如 /theme1 或者 /theme2。注意:各个主题的图片文件名要保持不变;图片路径是根据 theme.scss 里面引入图片样式的路径来决定的,可以根据项目实际情况进行调整。

详解Vue 换肤方案验证

以上,就是Vue项目实现换肤功能的一种方案。换肤功能的实现还有其他方法,欢迎一起交流学习。

Javascript 相关文章推荐
javascript中验证大写字母、数字和中文
Jan 15 Javascript
JavaScript获得指定对象大小的方法
Jul 01 Javascript
BootStrap中的table实现数据填充与分页应用小结
May 26 Javascript
Js获取当前日期时间及格式化代码
Sep 17 Javascript
利用js判断手机是否安装某个app的多种方案
Feb 13 Javascript
关于react中组件通信的几种方式详解
Dec 10 Javascript
React BootStrap用户体验框架快速上手
Mar 06 Javascript
vue的mixins属性详解
Mar 14 Javascript
Vue.js中 v-model 指令的修饰符详解
Dec 03 Javascript
亲自动手实现vue日历控件
Jun 26 Javascript
vue中组件通信的八种方式(值得收藏!)
Aug 09 Javascript
Vue项目打包、合并及压缩优化网页响应速度
Jul 07 Vue.js
Vue项目实现换肤功能的一种方案分析
Aug 28 #Javascript
js遍历详解(forEach, map, for, for...in, for...of)
Aug 28 #Javascript
Angular6使用forRoot() 注册单一实例服务问题
Aug 27 #Javascript
jQuery - AJAX load() 实例用法详解
Aug 27 #jQuery
JS实现提示框跟随鼠标移动
Aug 27 #Javascript
js对象数组和对象的使用实例详解
Aug 27 #Javascript
vue递归组件实战之简单树形控件实例代码
Aug 27 #Javascript
You might like
PHP命令行脚本接收传入参数的三种方式
2014/08/20 PHP
jquery键盘事件介绍
2011/01/31 Javascript
js的参数有长度限制吗?发现不能超过2083个字符
2014/04/20 Javascript
node.js中的fs.truncateSync方法使用说明
2014/12/15 Javascript
讲解JavaScript的Backbone.js框架的MVC结构设计理念
2016/02/14 Javascript
深入理解JavaScript程序中内存泄漏
2016/03/17 Javascript
Angular.js与Bootstrap相结合实现手风琴菜单代码
2016/04/13 Javascript
浅谈bootstrap使用中的一些问题以及解决过程
2016/10/18 Javascript
详解基于React.js和Node.js的SSR实现方案
2019/03/21 Javascript
JavaScript变量作用域及内存问题实例分析
2019/06/10 Javascript
简单了解JavaScript中常见的反模式
2019/06/21 Javascript
layui 富文本编辑器和textarea值的相互传递方法
2019/09/18 Javascript
vue实现跳转接口push 转场动画示例
2019/11/01 Javascript
Vue.js 中制作自定义选择组件的代码附演示demo
2020/02/28 Javascript
如何构建一个Vue插件并生成npm包
2020/10/26 Javascript
[08:07]DOTA2每周TOP10 精彩击杀集锦vol.8
2014/06/25 DOTA
[02:08]2018年度CS GO枪械皮肤设计大赛优秀作者-完美盛典
2018/12/16 DOTA
[50:48]LGD vs CHAOS 2019国际邀请赛小组赛 BO2 第二场 8.15
2019/08/16 DOTA
[04:05]TI9战队采访 - Natus Vincere
2019/08/22 DOTA
Python中的自省(反射)详解
2015/06/02 Python
python调用百度语音REST API
2018/08/30 Python
在 Python 中使用 7zip 备份文件的操作
2020/12/11 Python
详解html5 shiv.js和respond.min.js
2018/01/24 HTML / CSS
Forever 21美国官网:美国标志性快时尚品牌
2017/02/20 全球购物
世界上最大的家庭自动化公司:Smarthome
2017/12/20 全球购物
培训主管的岗位职责
2013/11/23 职场文书
校长岗位职责
2013/11/26 职场文书
学校学雷锋活动总结
2014/06/26 职场文书
中班下学期个人工作总结
2015/02/12 职场文书
歌舞青春观后感
2015/06/10 职场文书
生日宴会家属答谢词
2015/09/29 职场文书
亲情作文之母爱
2019/09/25 职场文书
Python利器openpyxl之操作excel表格
2021/04/17 Python
python 定义函数 返回值只取其中一个的实现
2021/05/21 Python
教你使用pyinstaller打包Python教程
2021/05/27 Python
SpringBoot 拦截器妙用你真的了解吗
2021/07/01 Java/Android