Vue项目使用CSS变量实现主题化
主题化管理经常能在网站上看到,一般的思路都是将主题相关的CSS样式独立出来,在用户选择主题的时候加载相应的CSS样式文件。现在大部分浏览器都能很好的兼容CSS变量,主题化样式更容易管理了。最近,使用CSS变量在Vue项目中做了一个主题化实践,下面来看看整个过程。
可行性测试
为了检验方法的可行性,在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变量实现主题化的更多相关文章
- <转载> VUE项目中CSS管理
vue的scoped 在vue项目中,当 .vue文件中 <style> 标签有 *scoped 属性时,它的 CSS 只作用于当前组件中的元素,很好的实现了样式私有化的目的. 使用sco ...
- 关于使用css变量实现主题的切换效果
现在要实现网页主题的切换成本较小的一种方案就是使用css的变量来实现 HTML 在HTML的body标签上先定义一个id元素属性 <body id="sm-theme"> ...
- vue项目的环境变量
关于项目中环境变量的总结 背景 项目环境一般分为开发环境,测试环境,线上环境 因为每个环境的接口域名.webpack 配置都是不同的,所以在打包构建时,我们需要区分这些环境,这时就用到了环境变量 在工 ...
- 解决vue项目中使用ivew定制主题报 .bezierEasingMixin();错误
背景:在使用view-design(iview)定制主体时(覆盖变量方式)出现less错误 完整错误如下 解决方法: 在vue.config.js中添加 less-loader:5.0.x modul ...
- vue项目中使用组件化开发
最近在使用vue-cli结合webpack打包工具开发一个后台管理系统,使用vue难免需要运用组件化思想,而这也正是vue的一大特点. 在之前做的vue项目中,稍微有一点组件化的思想,可能是对组件化不 ...
- 初次接触CSS变量
本文的目的主要是展示CSS变量是如何工作的.随着Web应用程序变得越来越大,CSS变得越来越大,越来越多,而且很多时候都很乱,在良好的上下文中使用CSS变量,为您提供重用和轻松更改重复出现的CSS属性 ...
- python 全栈开发,Day58(bootstrap组件,bootstrap JavaScript 插件,后台模板,图表插件,jQuery插件库,Animate.css,swiper,运行vue项目)
一.bootstrap组件 无数可复用的组件,包括字体图标.下拉菜单.导航.警告框.弹出框等更多功能. 组件和插件的区别? 插件:一个功能,比如js文件 组件:html css js 组件包含插件 面 ...
- vue项目中postcss-pxtorem的使用及webpack中的配置 css中单位px和em,rem的区别
移动手机版要求我们在制作嵌入h5的时候去适配不同的手机.适配有多重模式,有flex.百分比等.字体大小的控制也有px.百分比.rem等单位,webpack中 px转rem. vue项目中postcss ...
- vue-cli构建的vue项目打包后css引入的背景图路径不对的问题
使用vue-cli构建vue项目后,再打包遇到一个css引入的背景图片路径的问题,就是css代码中背景图片是根据相对路径来写的,如下图: 当使用npm run dev命令本地访问的时候,背景图片是正常 ...
随机推荐
- Vulnhub靶场渗透练习(三) bulldog
拿到靶场后先对ip进行扫描 获取ip 和端口 针对项目路径爆破 获取两个有用文件 http://192.168.18.144/dev/ dev,admin 更具dev 发现他们用到框架和语言 找到一 ...
- (三)Kinect姿势识别
Kinect给我们内置了许多姿势如举手等,具体可参考枚举KinectGestures.Gestures,也可以通过Kinect姿势管理器,自定义姿势导入(坑较多,内置的基本够用了)也可以根据关节坐标自 ...
- 23 个重难点突破,带你吃透 Service 知识点「长达 1W+ 字」
前言 学 Android 有一段时间了,想必不少人也和我一样,平时经常东学西凑,感觉知识点有些凌乱难成体系.所以趁着这几天忙里偷闲,把学的东西归纳下,捋捋思路. 这篇文章主要针对 Service 相关 ...
- 关于RocketMQ消息消费与重平衡的一些问题探讨
其实最好的学习方式就是互相交流,最近也有跟网友讨论了一些关于 RocketMQ 消息拉取与重平衡的问题,我姑且在这里写下我的一些总结. ## 关于 push 模式下的消息循环拉取问题 之前发表了一篇关 ...
- 对比讲解lambda表达式与传统接口函数实现方式
在本号之前写过的一些文章中,笔者使用了lambda表达式语法,一些读者反映说代码看不懂.本以为java 13都已经出了,java 8中最重要特性lambda表达式大家应该都掌握了,实际上还是存在大量的 ...
- 使用 HTML5 WebSocket 构建实时 Web 应用
原文地址:http://www.ibm.com/developerworks/cn/web/1112_huangxa_websocket/ HTML5 WebSocket 简介和实战演练 本文主要介绍 ...
- 查找一个卷对应的osd
1.首先找到卷的id: 2.使用rados命令找到卷上面的对象数据: 3.通过ceph osd map命令可以查询到对象对应的pgid及pg对应的osd:
- noip模拟9 达哥随单题
T1.随 看题第一眼,就瞄到最下面 孙金宁教你学数学 ?????原根?目测神题,果断跳过. 最后打了个快速幂,愉快的收到了达哥送来的10分. 实际上这题暴力不难想,看到一个非常小的mod应该就能想到 ...
- 梯度下降法及一元线性回归的python实现
梯度下降法及一元线性回归的python实现 一.梯度下降法形象解释 设想我们处在一座山的半山腰的位置,现在我们需要找到一条最快的下山路径,请问应该怎么走?根据生活经验,我们会用一种十分贪心的策略,即在 ...
- 关于数论分块里r=sum/(sum/l)的证明!
今天的模拟赛里T2要使用到数论分块,里面有一个重要的坎就是关于r=sum/(sum/l)的证明,网上关于这道题的题解里都没有关于这个的证明,那么我就来填补一下: 在以下的文章里,我都会使用lo(x)表 ...