主题化管理经常能在网站上看到,一般的思路都是将主题相关的CSS样式独立出来,在用户选择主题的时候加载相应的CSS样式文件。现在大部分浏览器都能很好的兼容CSS变量,主题化样式更容易管理了。最近,使用CSS变量在Vue项目中做了一个主题化实践,下面来看看整个过程。

Github项目地址

演示地址

可行性测试

为了检验方法的可行性,在public文件夹下新建一个themes文件夹,并在themes文件夹新建一个default.css文件:

:root {
--color: red;
}

在public文件夹的index.html文件中引入外部样式theme.css,如下:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title>vue-skin-peeler-demo</title>
<!-- 引入themes文件夹下的default.css -->
<link rel="stylesheet" type="text/css" href="src/themes/default.css" rel="external nofollow">
</head>
<body>
<noscript>
<strong>We're sorry but vue-skin-peeler-demo doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>

然后,在Home.vue中使用CSS变量:

<template>
<div class="home">
<div :class="$style.demo">变红色</div>
</div>
</template> <script>
export default {
name: 'home'
}
</script> <style module lang="scss">
.demo {
color: var(--color);
}
</style>

然后,运行项目并在浏览器中打开页面,页面显示效果正常。

注意:@vue/cli使用link标签引入css样式可能报错“We're sorry but vue-skin-peeler-demo doesn't work properly without JavaScript enabled. Please enable it to continue.”。这是因为@vue/cli将src目录下的文件都通过webpack打包所引起,所以,静态文件资源要放在public(如果是@vue/cli 2.x版本放在static)文件夹下。

实现主题切换

这里主题切换的思路是替换link标签的href属性,因此,需要写一个替换函数,在src目录下新建themes.js文件,代码如下:

// themes.js
const createLink = (() => {
let $link = null
return () => {
if ($link) {
return $link
}
$link = document.createElement('link')
$link.rel = 'stylesheet'
$link.type = 'text/css'
document.querySelector('head').appendChild($link)
return $link
}
})() /**
* 主题切换函数
* @param {string} theme - 主题名称, 默认default
* @return {string} 主题名称
*/
const toggleTheme = (theme = 'default') => {
const $link = createLink()
$link.href = `./themes/${theme}.css`
return theme
} export default toggleTheme

然后,在themes文件下创建default.css和dark.css两个主题文件。创建CSS变量,实现主题化。CSS变量实现主题切换请参考另一篇文章初次接触css变量

兼容性

IE浏览器以及一些旧版浏览器不支持CSS变量,因此,需要使用css-vars-ponyfill,是一个ponyfill,可在旧版和现代浏览器中为CSS自定义属性(也称为“ CSS变量”)提供客户端支持。由于要开启watch监听,所以还有安装MutationObserver.js

安装:

npm install css-vars-ponyfill mutationobserver-shim --save

然后,在themes.js文件中引入并使用:

// themes.js
import 'mutationobserver-shim'
import cssVars from 'css-vars-ponyfill' cssVars({
watch: true
}) const createLink = (() => {
let $link = null
return () => {
if ($link) {
return $link
}
$link = document.createElement('link')
$link.rel = 'stylesheet'
$link.type = 'text/css'
document.querySelector('head').appendChild($link)
return $link
}
})() /**
* 主题切换函数
* @param {string} theme - 主题名称, 默认default
* @return {string} 主题名称
*/
const toggleTheme = (theme = 'default') => {
const $link = createLink()
$link.href = `./themes/${theme}.css`
return theme
} export default toggleTheme

开启watch后,在IE 11浏览器点击切换主题开关不起作用。因此,每次切换主题时都重新执行cssVars(),还是无法切换主题,原因是开启watch后重新执行cssVars()是无效的。最后,只能先关闭watch再重新开启。成功切换主题的themes.js代码如下:

// themes.js
import 'mutationobserver-shim'
import cssVars from 'css-vars-ponyfill' const createLink = (() => {
let $link = null
return () => {
if ($link) {
return $link
}
$link = document.createElement('link')
$link.rel = 'stylesheet'
$link.type = 'text/css'
document.querySelector('head').appendChild($link)
return $link
}
})() /**
* 主题切换函数
* @param {string} theme - 主题名称, 默认default
* @return {string} 主题名称
*/
const toggleTheme = (theme = 'default') => {
const $link = createLink()
$link.href = `./themes/${theme}.css`
cssVars({
watch: false
})
setTimeout(function () {
cssVars({
watch: true
})
}, 0)
return theme
} export default toggleTheme

查看所有代码,请移步Github项目地址

记住主题

实现记住主题这个功能,一是可以向服务器保存主题,一是使用本地存储主题。为了方便,这里主要使用本地存储主题的方式,即使用localStorage存储主题。具体实现请移步Github项目地址

Vue项目使用CSS变量实现主题化的更多相关文章

  1. <转载> VUE项目中CSS管理

    vue的scoped 在vue项目中,当 .vue文件中 <style> 标签有 *scoped 属性时,它的 CSS 只作用于当前组件中的元素,很好的实现了样式私有化的目的. 使用sco ...

  2. 关于使用css变量实现主题的切换效果

    现在要实现网页主题的切换成本较小的一种方案就是使用css的变量来实现 HTML 在HTML的body标签上先定义一个id元素属性 <body id="sm-theme"> ...

  3. vue项目的环境变量

    关于项目中环境变量的总结 背景 项目环境一般分为开发环境,测试环境,线上环境 因为每个环境的接口域名.webpack 配置都是不同的,所以在打包构建时,我们需要区分这些环境,这时就用到了环境变量 在工 ...

  4. 解决vue项目中使用ivew定制主题报 .bezierEasingMixin();错误

    背景:在使用view-design(iview)定制主体时(覆盖变量方式)出现less错误 完整错误如下 解决方法: 在vue.config.js中添加 less-loader:5.0.x modul ...

  5. vue项目中使用组件化开发

    最近在使用vue-cli结合webpack打包工具开发一个后台管理系统,使用vue难免需要运用组件化思想,而这也正是vue的一大特点. 在之前做的vue项目中,稍微有一点组件化的思想,可能是对组件化不 ...

  6. 初次接触CSS变量

    本文的目的主要是展示CSS变量是如何工作的.随着Web应用程序变得越来越大,CSS变得越来越大,越来越多,而且很多时候都很乱,在良好的上下文中使用CSS变量,为您提供重用和轻松更改重复出现的CSS属性 ...

  7. python 全栈开发,Day58(bootstrap组件,bootstrap JavaScript 插件,后台模板,图表插件,jQuery插件库,Animate.css,swiper,运行vue项目)

    一.bootstrap组件 无数可复用的组件,包括字体图标.下拉菜单.导航.警告框.弹出框等更多功能. 组件和插件的区别? 插件:一个功能,比如js文件 组件:html css js 组件包含插件 面 ...

  8. vue项目中postcss-pxtorem的使用及webpack中的配置 css中单位px和em,rem的区别

    移动手机版要求我们在制作嵌入h5的时候去适配不同的手机.适配有多重模式,有flex.百分比等.字体大小的控制也有px.百分比.rem等单位,webpack中 px转rem. vue项目中postcss ...

  9. vue-cli构建的vue项目打包后css引入的背景图路径不对的问题

    使用vue-cli构建vue项目后,再打包遇到一个css引入的背景图片路径的问题,就是css代码中背景图片是根据相对路径来写的,如下图: 当使用npm run dev命令本地访问的时候,背景图片是正常 ...

随机推荐

  1. openssl之DH(Diffie–Hellman)加密

    //加密机制初始化 g_HDMgr.init(); //对方的public key BIGNUM* peerPubKey = NULL; peerPubKey = BN_bin2bn((unsigne ...

  2. Open vSwitch系列之一 Open vSwitch诞生

    Open vSwitch系列之一 Open vSwitch诞生 Open vSwitch系列之二 安装指定版本ovs 2006年,SDN诞生于美国GENI项目资助的斯坦福大学Clean Slate课题 ...

  3. ESP8266开发之旅 网络篇② ESP8266 工作模式与ESP8266WiFi库

        在网络篇①中,博主主要讲解了Arduino上开发ESP8266的插件库 Arduino Core For ESP8266.但是,并没有讲到关于这个模块的工作模式,所以本篇讲着重讲解ESP826 ...

  4. Spring Boot2 系列教程(十七)SpringBoot 整合 Swagger2

    前后端分离后,维护接口文档基本上是必不可少的工作. 一个理想的状态是设计好后,接口文档发给前端和后端,大伙按照既定的规则各自开发,开发好了对接上了就可以上线了.当然这是一种非常理想的状态,实际开发中却 ...

  5. git jenkins SonarQube手动代码质检

    SonarQube代码质检:1.提交代码-->gitlab-->jenkins抓取-->sonarqube质量检测-->maven编译-->shell-->web集 ...

  6. Java学习笔记五--String(二)String其他方法

    第一节课 // 清除单位字符串开始和结尾空白的副本 String.trim(); 字符串每次更改都会创建新的对象,而不会覆盖原来的字符串,每次拼接都会产生新的String对象,耗时耗内存. java. ...

  7. angularjs通过ng-bind-html指令和$sce服务绑定html

    代码: <!doctype html> <html lang="en"> <head> <meta charset="UTF-8 ...

  8. 文件的处理(day09整理)

    目录 昨日回顾 二十八.字符编码 1.什么是字符编码 2.字符编码的发展史 3.gbk和gb2312 二十九.python2和python3的区别 python解释器启动的流程 今日内容 三十.文件处 ...

  9. ERP 到底是什么? 一则故事搞懂ERP

    你知道什么是ERP? ERP是什么? 你知道什么是ERP吗? (通俗易懂版) 一个故事搞懂“ERP” 一天中午,丈夫在外给家里打电话:“亲爱的老婆,晚上我想带几个同事回家吃饭可以吗?”(订货意向) 妻 ...

  10. Bash 内置高效特性

    变量(字符串)变换 定义一个变量t,内容为framE [root@vm1 tmp]# t=framE 查看变量t的内容:echo $t或者是echo ${t} [root@vm1 tmp]# echo ...