11

前言

【vue-koa2全栈撸win10风格管理系统】交个朋友系列文章,带各位全栈撸win10风格管理系统开发,当然项目也参考很多优秀的前后端项目构建方案和我在工作中的一些中的一些经验应用,主要是交个朋友的心态,如果你对这个项目有兴趣,也希望你的加入一起完善维护这个项目,let go~~~

完整项目地址:vue-win10-admin

本篇文章是【Vue+Koa2+Mysql全栈撸win10风格管理系统】交个朋友系列之主题切换方案

先来一个主题切换效果图,主要实现背景图片的切换和主题色的切换,而且刷新浏览器还是能保持

一、实现功能主要技术点

1、利用localStorage浏览器本地存储主题设置信息(当然也可以存储在数据库里)
2、scss抽离主题文件中涉及到颜色的 CSS 值替换成关键词
3、实时监听localStorage的变化,关键词再换回生成的相应的颜色值或者背景图片

二、抽取主题变量,封装mixin

在目录 styles/theme-variable.scss先把主题文件中涉及到颜色的 CSS 值替换成关键词,做了个别地方进行皮肤切换

$background-color-theme1: #409EFF;
$background-color-theme2: #0078D7;
$background-color-theme3: #C30052;
$background-color-theme4: #9A0089;
$background-color-theme5: #67C23A;
$background-color-theme6: #CA5010;
$background-color-theme7: #CA5010;
$background-color-theme8: red;
$background-color-theme9: #303133;
$background-color-theme10: #606266;
$background-color-theme11: #909399;
$background-color-theme12: #C0C4CC;
$background-color-theme13: #DCDFE6;
$background-color-theme14: #E4E7ED;
$background-color-theme15: #EBEEF5;
$background-color-theme16: #FFFFFF;

$font-color-black: #303133;
$font-color-white: #FFFFFF;

$startMenu-background-color-black: rgba(19, 23, 28, 0.9);
$startMenu-background-color-white: #F2F6FC;

在目录 styles/theme-mixin.scss 设置背景颜色封装成一个mixin方法(包括字体大小,字体颜色,进行封装),@mixin通过自定义属性[data-theme=""]去识别对应的颜色变量

@mixin background-color($color) {
 background-color: $color;
 [data-theme="theme1"] & {
   background-color:$background-color-theme1;
 }
 [data-theme="theme2"] & {
   background-color:$background-color-theme2;
 }
 [data-theme="theme3"] & {
   background-color:$background-color-theme3;
 }
 [data-theme="theme4"] & {
   background-color:$background-color-theme4;
 }
 [data-theme="theme5"] & {
   background-color:$background-color-theme5;
 }
 [data-theme="theme6"] & {
   background-color:$background-color-theme6;
 }
 [data-theme="theme7"] & {
   background-color:$background-color-theme7;
 }
 [data-theme="theme8"] & {
   background-color:$background-color-theme8;
 }
 [data-theme="theme9"] & {
   background-color:$background-color-theme9;
 }
 [data-theme="theme10"] & {
   background-color:$background-color-theme10;
 }
 [data-theme="theme11"] & {
   background-color:$background-color-theme11;
 }
 [data-theme="theme12"] & {
   background-color:$background-color-theme12;
 }
 [data-theme="theme13"] & {
   background-color:$background-color-theme13;
 }
 [data-theme="theme14"] & {
   background-color:$background-color-theme14;
 }
 [data-theme="theme15"] & {
   background-color:$background-color-theme15;
 }
 [data-theme="theme16"] & {
   background-color:$background-color-theme16;
 }
}

在页面上需要用到切换肤色的地方引用样

@import "~@/styles/theme-mixin.scss";
 @import "@/styles/theme-variable.scss";
 @include background-color($background-color-theme1); //引用背景颜色设置
 @include font-color($font-color-white); //引用字体设置
 

例如在layout页面布局里相关文件里(部分展示),这里是基础scss技能不再做过多的讲解

<style lang="scss" scoped>
@import "~@/styles/theme-mixin.scss";
@import "@/styles/theme-variable.scss";
.window-wrapper {
position: absolute;
min-width: 1280px;
min-height: 80%;
z-index: 9;
.window-header {
  height: 40px;
  line-height: 40px;
  @include background-color($background-color-theme1);
  transition: all .5s;
  display: flex;

  .window-title {
    flex: 1;
    padding-left: 10px;
    user-select: none;
    color: #fff;
    @include font-color($font-color-white);
    transition: all .5s;

三、主题颜色设置

在目录 src/views/config/coloer/index.vue 中更换主题时的操作代码

<template>
  <div class="colour-wrapper">
    <preview></preview>
    <div class="set-wrapper">
      <div class="title">主题色</div>
      <div class="colour-list">
        <div v-for="index of 16" :key="index" :class="'theme-color-'+index" @click="changeTheme(index)"></div>
      </div>
    </div>
  </div>
</template>

<script>
import preview from '@/components/preview.vue'
import { localKey } from '@/settings'
export default {
  components: {
    preview
  },
 data() {
    return {
    }
  },
 methods:{
   changeTheme(index) {
     let theme = "theme" + index
    window.document.documentElement.setAttribute('data-theme', theme)
   } 
 }
}
</script>

通过再选择主题的时候,我在这里主题色16个可以选择,列表是用v-for
列表渲染出来的,每个颜色绑定一个一个点击事件,通过DOM操作在设置自定义属性[data-theme],会在html里添加自定义属性data-theme,这样就是实现了皮肤切换

但是这样有什么缺点呢?

当你刷新浏览器的时候,你会发现这个设置就不生效了,
所以接下来考虑存储到浏览器缓存里去

四、localStorage本地存储主题设置

总所周知,vue无法监听localstorage的变化的,这里通过注册全局方法,然后通过事件派发的方式实现localstorage的响应式
根据我们项目中的主题相关的属性,目前有主题和背景图相关的设置存储在一个对象里
我们在 src/utils/storage.js里针对原生localStorage 的api都封装一层,生成自己的公用主题设置模块存储派发模块

export const dispatchSetLocalStore = (key, type, value) => {
  let settings = _getLocalStore(key,'JSONStr') || {
    theme: 11,
    taskbarMode: 'bottom',
    bgSrc: ''
  }
  switch(type) {
    case 'bgSrc':
      settings.bgSrc = value
      break
    case 'theme':
      settings.theme = value
      break
    case 'taskbarMode':
      settings.taskbarMode = value
      break
  }
  settings = JSON.stringify(settings)
    // 创建一个StorageEvent事件
  let newStorageEvent = document.createEvent('StorageEvent');
  const storage = {
      setItem: function (k, val) {
        localStorage.setItem(k, val)
        // 初始化创建的事件
        newStorageEvent.initStorageEvent('setItem', false, false, k, null, val, null, null)
        // 派发对象
        window.dispatchEvent(newStorageEvent)
      }
  }
  return storage.setItem(key, settings)
}

然后在src/main.js对vue添加一个原型属性

import { dispatchSetLocalStore } from './utils/storage'
Vue.prototype.setLocalStore = dispatchSetLocalStore

此时此刻我们就可以在vue文件里监听到变化了

<template>
  <div id="app"  :style="{ background: 'url('+bgSrc+')'}" :data-theme="theme">
    <router-view />
  </div>
</template>

<script>
import { _getLocalStore } from '@/utils/storage'
import { localKey } from '@/settings'
export default {
  name: 'App',
  data() {
   return {
     bgSrc: _getLocalStore(localKey, 'JSONStr') && _getLocalStore(localKey, 'JSONStr').bgSrc  ? _getLocalStore(localKey, 'JSONStr').bgSrc : require('@/assets/bg_01.jpg'),
     theme: _getLocalStore(localKey, 'JSONStr') && _getLocalStore(localKey, 'JSONStr').theme  ? _getLocalStore(localKey, 'JSONStr').theme : 'theme1'
    }
  },
  created(){
    window.addEventListener('setItem', () => {
      let local = _getLocalStore(localKey, 'JSONStr')
      this.bgSrc = local && local.bgSrc ? local.bgSrc : this.bgSrc
      this.theme = local && local.theme ? local.theme : this.theme
    })
  },
}
</script>

在目录 src/views/config/coloer/index.vue 中更换主题时的操作代码
此时就不是 window.document.documentElement.setAttribute('data-theme', theme)
而是this.setLocalStore(localKey, 'theme', theme)

五、总结

换肤的方式主要是对涉及到颜色的 CSS 值替换成关键词,根据用户选择的主题色生成一系列对应的颜色值,用户选的主题设和背景图片统统通过键值对存储在localstorage,然后通过全局事件派发,响应式获取localstorage,通过自定义属性的属性值,对应把关键词再换回刚刚生成的相应的颜色值,切换背景图片,然后分别对其加一些切换动画,显得换肤和切换背景图片自然~
【Vue+Koa2+Mysql全栈撸win10风格管理系统】交个朋友系列文章,会根据项目搭建和讲功能点实现,欢迎大家一起交流~
完整项目地址:vue-win10-admin


codercao
395 声望19 粉丝