网上很多方法都采用scss,现在用原生css实现一种简单版

mode.vue(随便定义名称):

	// 在data里面定义mode为false
	/*
    * 模式切换
    * */
    fnChangeMode(){
      this.mode = !this.mode;
      if (this.mode == true) {
        window.document.documentElement.setAttribute('data-theme', 'dark')
      } else {
        window.document.documentElement.setAttribute('data-theme', 'light')
      }
    }
/**
注意这里的css样式必须使用全局,不能加scoped标签!!!
**/
<style>
  :root[data-theme=dark]  {
    /* 模式切换变量,默认light模式 */
    --current-background-color: var(--dark-background-color);
    --current-primary-color: var(--dark-primary-color);

    /* 深色主题 */
    --dark-primary-color: #fff;
    --dark-background-color: #282c34;
  }

  :root[data-theme=light]  {
    /* 模式切换变量,默认light模式 */
    --current-background-color: var(--light-background-color);
    --current-primary-color: var(--light-primary-color);

    /* 浅色主题 */
    --light-primary-color: #666;
    --light-background-color: #fff;
  }

  .header-wrap {
    height: 60px;
    background-color: var(--current-background-color);
    display: flex;
    justify-content: space-between;
    align-items: center;
    box-shadow: 0 1px 4px rgba(0, 21, 41, 0.08);
  }

  .mode{
    margin-right: 20px;
    cursor: pointer;
    color:var(--current-primary-color)!important;
  }
</style>

升级版(支持ie)

app.vue

#app {
  background: var(--fill-1);
}

utils/theme.js

import { lightTheme, darkTheme } from '../less/variable';
import cssVars from 'css-vars-ponyfill';

export const initTheme = theme => {
  document.documentElement.setAttribute('data-theme', theme);
  cssVars({
    watch: true, // 当添加,删除或修改其<link>或<style>元素的禁用或href属性时,ponyfill将自行调用
    variables: theme == 'dark' ? darkTheme : lightTheme, // variables 自定义属性名/值对的集合
    onlyLegacy: false, // false  默认将css变量编译为浏览器识别的css样式  true 当浏览器不支持css变量的时候将css变量编译为识别的css
  });
};

variable.js

//浅色
export const lightTheme = {
  '--fill-1': '#fff',
  '--text': '#3c3c3c',
  '--slide-arrow': '#000000',
};

// 深色
export const darkTheme = {
  '--fill-1': '#222',
  '--text': '#fff',
  '--slide-arrow': '#f2f2f2',
  '--text-1': 'rgba(255, 255, 255, 0.3)',
  '--text-2': '#ffcd32',
};

header.vue(随便定义,作用用于切换样式)

import { initTheme } from '@/utils/theme';
export default {
  name: 'Header',
  data() {
    return {
      theme: 'dark',
    };
  },
  methods: {
    changeTheme() {
      this.theme == 'light' ? (this.theme = 'dark') : (this.theme = 'light');
      initTheme(this.theme);
    },
  },
  created() {
    initTheme(this.theme);
  },
};

方案2(一行代码实现)

html {
    filter: invert(1) hue-rotate(180deg);
}

本次的暗黑模式使用到两个滤镜函数:invert()、hue-rotate()。

invert():反相,反向输出图像着色,值为0%则无变化,值为0~100%则是线性乘子效果,值为100%则完全反转

hue-rotate():色相旋转,减弱图像着色,处理非黑白的颜色,值为0deg则无变化,值为0~360deg则逐渐减弱,值超过360deg则相当绕N圈再计算剩余的值

invert()简单理解就是黑变白,白变黑,黑白颠倒。hue-rotate()简单理解就是冲淡颜色。为了确保主题色调不会改变,将色相旋转声明为180deg比较合理。

按照设计原则来说,换肤只针对组件,像一些媒体类型的元素,例如背景、图片、视频等,都是不能直接处理的,需保持其原样。既然暗黑模式是使用了滤镜的反相和色相旋转实现,那么对这些媒体元素再次使用滤镜的反相和色相旋转就能复原了。

img,
video {
    filter: invert(1) hue-rotate(180deg);
}
整体代码
<body>
    <input class="ios-switch" type="checkbox">
    <div class="main">网站主体</div>
</body>
.ios-switch {
    ...
    &:checked {
        ...
        & + .main {
            filter: invert(1) hue-rotate(180deg);
            img,
            video,
            .exclude {
                filter: invert(1) hue-rotate(180deg);
            }
        }
    }
}
.main {
    background-color: #fff;
    transition: all 300ms;
}

方案3(element切换)

参考:https://blog.csdn.net/sinat_29740819/article/details/89710590?utm_medium=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.control&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.control

Logo

前往低代码交流专区

更多推荐