先看效果

在这里插入图片描述
在这里插入图片描述

以上是两种主题方案

进入实现方法和讲解

原理:
 <view class="dark-bg" :style="{'--text-color': color}"> // 注意这里的 text-color
    <view class="h2">测试组件</view>
    <view>
      <select-theme></select-theme>
    </view>
    <view class="h2">背景测试</view>
    <view class="bg-test"></view>
    <view class="h2">字体测试</view>
    <view class="font-test">
      <view>普通字体</view>
      <view class="font-btn">按钮字体</view>
    </view>
  </view>

–text-color :

可以理解为一个style的属性变量,只要操作后边的color变量就可以实现颜色动态改变

声明变量:

theme.scss

/* 普通字体颜色 */
$text-color: var(--text-color);
/* 按钮字体颜色 */
$text-color-reverse: var(--text-color-reverse);
/* tab字体颜色 */
$text-color-tab: var(--text-color-tab);

/* 普通背景颜色 */
$bg-color: var(--bg-color);

/* 普通阴影颜色 */
$bg-shadow: var(--bg-shadow);

/* 主题颜色 */
$theme-color: var(--theme-color);

vuex 中定义主题颜色和方案

export default {
  namespaced: true,
  state: {
    // 深色系主题
    dark: {
      '--text-color': '#000000',
      '--text-color-reverse': '#ccc9bd',
      '--text-color-tab': '#ddd8be',
      '--bg-color': '#0000004d',
      '--bg-shadow': '#e9ead82e'
    },
    // 浅色系主题
    light: {
      '--text-color': '#ffffff',
      '--text-color-reverse': '#333642',
      '--text-color-tab': '#222741',
      '--bg-color': '#ffffff4d',
      '--bg-shadow': '#1615272e'
    },
    // 主题方案
    scheme: ['dark', 'light'],
    // 当前主题
    theme: 'light'
  },
  getters: {
    theme(state) {
      return state[state.theme]
    }
  },
  mutations: {
    updateTheme(state, { theme, message = '主题切换完成' }) {
      if (state.scheme.includes(theme)) {
        state.theme = theme
        message &&
          uni.showToast({
            title: message,
            icon: 'none'
          })
      } else {
        console.warn(new Error('不存在的主题类型'))
      }
    }
  }
}

由上可见:

getters中会根据state中当前的主题方案theme来读取state中的不同方案;
给到页面中的style就可以了,这样这个有style属性的子级元素就可以使用此变量

使用:

<template>
  <view class="dark-bg" :style="theme">
    <view class="h2">测试组件</view>
    <view>
      <select-theme></select-theme>
    </view>
    <view class="h2">背景测试</view>
    <view class="bg-test"></view>
    <view class="h2">字体测试</view>
    <view class="font-test">
      <view>普通字体</view>
      <view class="font-btn">按钮字体</view>
    </view>
  </view>
</template>

<script>
import SelectTheme from '@/components/select-theme'
import { mapGetters } from 'vuex'
export default {
  components: {
    SelectTheme
  },
  computed: {
    ...mapGetters('theme', ['theme'])
  }
}
</script>

<style scoped lang="scss">
.dark-bg {
  width: 100vw;
  height: 100vh;
  font-size: 16px;
  background: #33333390;
  color: $text-color;
}
.h2 {
  font-size: 20px;
  font-weight: bold;
}
.px-class {
  width: 100px;
  height: 100px;
  background: $success-color;
}
.bg-test {
  width: 300px;
  height: 160px;
  border-radius: 10px;
  background: $bg-color;
}
.font-test {
  color: $text-color;
  .font-btn {
    color: $text-color-reverse;
  }
}
</style>

select-theme组件:

<template>
  <view>
    <view class="select">
      <view
        :class="[{ 'active-ele': theme === item }]"
        v-for="item in scheme"
        :key="item"
        @click="selectChange(item)"
        >{{ item }}</view
      >
    </view>
  </view>
</template>

<script>
import { mapMutations, mapGetters, mapState } from 'vuex'
export default {
  computed: {
    ...mapGetters('theme', ['theme']),
    ...mapState('theme', ['theme', 'scheme'])
  },
  methods: {
    ...mapMutations('theme', ['updateTheme']),
    selectChange(theme) {
      this.updateTheme({ theme })
    }
  }
}
</script>

<style scoped lang="scss">
.select {
  > view {
    padding: 5px 15px;
    border-radius: 10px;
    display: inline-block;
    cursor: pointer;
  }
}
.active-ele {
  background: $success-color;
  color: $text-color-tab;
}
</style>
Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐