主题化管理经常能在网站上看到, 一般的思路都是将主题相关的 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 变量, 因此, 需要使用 https://github.com/jhildenbiddle/css-vars-ponyfill , 是一个 https://github.com/sindresorhus/ponyfill , 可在旧版和现代浏览器中为 CSS 自定义属性 (也称为 "CSS 变量") 提供客户端支持. 由于要开启 watch 监听, 所以还有安装 https://github.com/megawac/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 项目地址.
来源: https://www.cnblogs.com/jofun/p/11917401.html