详解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 相关文章推荐
jQuery 1.0.2
Oct 11 Javascript
jQuery 判断页面元素是否存在的代码
Aug 14 Javascript
javascript工厂模式和构造函数模式创建对象方法解析
Dec 30 Javascript
一个例子轻松学会Vue.js
Jan 02 Javascript
ES6中新增的Object.assign()方法详解
Sep 22 Javascript
angular2路由之routerLinkActive指令【推荐】
May 30 Javascript
在小程序中使用canvas的方法示例
Sep 17 Javascript
用vue-cli开发vue时的代理设置方法
Sep 20 Javascript
vue项目中使用Hbuilder打包app 设置沉浸式状态栏的方法
Oct 22 Javascript
vue中改变滚动条样式的方法
Mar 03 Javascript
微信小程序报错: thirdScriptError的错误问题
Jun 19 Javascript
vue完美实现el-table列宽自适应
May 08 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
使用 php4 加速 web 传输
2006/10/09 PHP
PHP和Mysqlweb应用开发核心技术 第1部分 Php基础-1 开始了解php
2011/07/03 PHP
PHP实现绘制3D扇形统计图及图片缩放实例
2014/10/01 PHP
用户注册常用javascript代码
2009/08/29 Javascript
jQuery 开天辟地入门篇一
2009/12/09 Javascript
js获取url参数值的两种方式
2013/09/10 Javascript
javascript对JSON数据排序的3个例子
2014/04/12 Javascript
IE浏览器中图片onload事件无效的解决方法
2014/04/29 Javascript
jquery数组过滤筛选方法grep()简介
2014/06/06 Javascript
jquery实现经典的淡入淡出选项卡效果代码
2015/09/22 Javascript
Angularjs中的事件广播 —全面解析$broadcast,$emit,$on
2016/05/17 Javascript
JS实现回到页面顶部动画效果的简单实例
2016/05/24 Javascript
AngularJS基础 ng-paste 指令简单示例
2016/08/02 Javascript
javascript构造函数以及原型对象的理解
2017/01/13 Javascript
JavaScript 巧学巧用
2017/05/23 Javascript
vue使用axios实现文件上传进度的实时更新详解
2017/12/20 Javascript
VueCli3构建TS项目的方法步骤
2018/11/07 Javascript
vue v-for 使用问题整理小结
2019/08/04 Javascript
js实现的在本地预览图片功能示例
2019/11/09 Javascript
vue使用nprogress加载路由进度条的方法
2020/06/04 Javascript
[57:24]LGD vs VGJ.T 2018国际邀请赛小组赛BO2 第二场 8.16
2018/08/17 DOTA
[07:01]DOTA2-DPC中国联赛正赛 Aster vs Magma 3月5日 赛后选手采访
2021/03/11 DOTA
python list语法学习(带例子)
2013/11/01 Python
python 排序算法总结及实例详解
2016/09/28 Python
Python下的Softmax回归函数的实现方法(推荐)
2017/01/26 Python
python实现windows下文件备份脚本
2018/05/27 Python
Python除法之传统除法、Floor除法及真除法实例详解
2019/05/23 Python
python调用自定义函数的实例操作
2019/06/26 Python
Hotter Shoes英国官网:英伦风格,舒适的鞋子
2017/12/28 全球购物
教师自我评价范例
2013/09/24 职场文书
公证委托书模板
2014/04/03 职场文书
《社戏》教学反思
2014/04/15 职场文书
邀请函模板
2015/02/02 职场文书
幼儿园庆六一主持词
2015/06/30 职场文书
户外拓展训练感想
2015/08/07 职场文书
golang为什么要统一错误处理
2022/04/03 Golang