详解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 相关文章推荐
Expandable "Detail" Table Rows
Aug 29 Javascript
在IE 浏览器中使用 jquery的fadeIn() 效果 英文字符字体加粗
Jun 02 Javascript
js计算字符串长度包含的中文是utf8格式
Oct 15 Javascript
JS制作手机端自适应缩放显示
Jun 11 Javascript
微信小程序 wx.request(OBJECT)发起请求详解
Oct 13 Javascript
基于Vue2的移动端开发环境搭建详解
Nov 03 Javascript
angular ng-click防止重复提交实例
Jun 16 Javascript
详解JS模块导入导出
Dec 20 Javascript
集成vue到jquery/bootstrap项目的方法
Feb 10 jQuery
微信小程序开发注意指南和优化实践(小结)
Jun 21 Javascript
Vue 简单实现前端权限控制的示例
Dec 25 Vue.js
vue 数据双向绑定的实现方法
Mar 04 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中func_get_args(),func_get_arg(),func_num_args()的区别
2013/09/30 PHP
FleaPHP框架数据库查询条件($conditions)写法总结
2016/03/19 PHP
thinkphp自带验证码全面解析
2016/09/18 PHP
PHP弱类型语言中类型判断操作实例详解
2017/08/10 PHP
Mootools 1.2教程(2) DOM选择器
2009/09/14 Javascript
实现web打印的各种方法介绍及实现代码
2013/01/09 Javascript
JavaScript 函数惰性载入的实现及其优点介绍
2013/08/12 Javascript
js 实现菜单上下显示附效果图
2013/11/21 Javascript
Extjs Label的 fieldLabel和html属性值对齐的方法
2014/06/15 Javascript
JavaScript节点及列表操作实例小结
2015/08/05 Javascript
基于jquery实现的仿优酷图片轮播特效代码
2016/01/13 Javascript
Jquery+ajax+JAVA(servlet)实现下拉菜单异步取值
2016/03/23 Javascript
JavaScript事件学习小结(五)js中事件类型之鼠标事件
2016/06/09 Javascript
jQuery根据name属性进行查找的用法分析
2016/06/23 Javascript
基于复选框demo(分享)
2017/09/27 Javascript
360提示[高危]使用存在漏洞的JQuery版本的解决方法
2017/10/27 jQuery
jQuery实现form表单序列化转换为json对象功能示例
2018/05/23 jQuery
django使用channels2.x实现实时通讯
2018/11/28 Javascript
JavaScript中import用法总结
2019/01/20 Javascript
Node.js Stream ondata触发时机与顺序的探索
2019/03/08 Javascript
Vue可自定义tab组件用法实例
2019/10/24 Javascript
vue 解决addRoutes多次添加路由重复的操作
2020/08/04 Javascript
Openlayers测量距离与面积的实现方法
2020/09/25 Javascript
[02:49]DAC2018决赛日TOP5 LGD开启黑暗之门绝杀VP
2018/04/08 DOTA
[00:29]2019完美世界全国高校联赛(秋季赛)总决赛海口落幕
2019/12/10 DOTA
Python二维码生成库qrcode安装和使用示例
2014/12/16 Python
pytorch 在sequential中使用view来reshape的例子
2019/08/20 Python
python将数组n等分的实例
2019/12/02 Python
Python 实现自动完成A4标签排版打印功能
2020/04/09 Python
可自定义箭头样式的CSS3气泡提示框
2016/03/16 HTML / CSS
什么是命名空间(NameSpace)
2015/11/24 面试题
校园歌手大赛策划书
2014/01/17 职场文书
质量标语大全
2014/06/12 职场文书
教师批评与自我批评材料
2014/10/16 职场文书
北京爱情故事观后感
2015/06/12 职场文书
斗罗大陆八大特殊魂兽,龙族始祖排榜首,第五最残忍(翠魔鸟)
2022/03/18 国漫