主题与样式的动态切换
主题与样式的动态切换
uni-app 开发中,动态切换主题和样式能显著提升用户体验。通过灵活配置,一套代码可适配多种视觉风格,满足不同场景需求。
基础实现方案
CSS 变量是实现动态主题的核心技术。在 uni.scss
中定义全局变量:
:root {
--primary-color: #007AFF;
--bg-color: #FFFFFF;
--text-color: #333333;
}
.dark-theme {
--primary-color: #0A84FF;
--bg-color: #1C1C1E;
--text-color: #F2F2F7;
}
组件中使用这些变量:
<template>
<view class="container">
<text class="title">动态主题示例</text>
</view>
</template>
<style>
.container {
background-color: var(--bg-color);
}
.title {
color: var(--text-color);
}
</style>
状态管理方案
通过 Vuex 或 Pinia 管理主题状态更高效:
// store/theme.js
export default {
state: {
currentTheme: 'light'
},
mutations: {
switchTheme(state, theme) {
state.currentTheme = theme
}
}
}
页面中切换主题:
<script>
import { mapState, mapMutations } from 'vuex'
export default {
computed: {
...mapState(['currentTheme'])
},
methods: {
...mapMutations(['switchTheme']),
toggleTheme() {
const newTheme = this.currentTheme === 'light' ? 'dark' : 'light'
this.switchTheme(newTheme)
document.documentElement.className = newTheme + '-theme'
}
}
}
</script>
动态样式绑定
结合条件类和样式对象实现更灵活的样式控制:
<template>
<button
:class="['btn', themeClass]"
:style="buttonStyle"
@click="handleClick"
>
切换主题
</button>
</template>
<script>
export default {
data() {
return {
isDark: false
}
},
computed: {
themeClass() {
return this.isDark ? 'dark-theme' : 'light-theme'
},
buttonStyle() {
return {
backgroundColor: this.isDark ? '#333' : '#EEE',
color: this.isDark ? '#FFF' : '#000'
}
}
},
methods: {
handleClick() {
this.isDark = !this.isDark
}
}
}
</script>
多平台适配方案
不同平台可能需要特殊处理:
// 判断平台
function getPlatformTheme() {
#ifdef H5
return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'
#endif
#ifdef APP-PLUS
return plus.navigator.getUIStyle() === 'dark' ? 'dark' : 'light'
#endif
return 'light'
}
主题持久化
使用本地存储保持用户选择:
// utils/theme.js
export function saveTheme(theme) {
uni.setStorageSync('selectedTheme', theme)
}
export function loadTheme() {
return uni.getStorageSync('selectedTheme') || 'light'
}
应用启动时加载:
// App.vue
export default {
onLaunch() {
const savedTheme = loadTheme()
this.$store.commit('switchTheme', savedTheme)
document.documentElement.className = savedTheme + '-theme'
}
}
高级主题切换动画
添加过渡效果提升体验:
<template>
<view class="theme-transition" :class="currentTheme">
<!-- 页面内容 -->
</view>
</template>
<style>
.theme-transition {
transition: background-color 0.3s ease, color 0.3s ease;
}
</style>
动态图标切换
根据主题切换图标资源:
<template>
<image :src="themeIcon" mode="aspectFit" />
</template>
<script>
export default {
computed: {
themeIcon() {
return this.$store.state.currentTheme === 'dark'
? '/static/icon-dark.png'
: '/static/icon-light.png'
}
}
}
</script>
主题配置系统
建立可扩展的主题配置:
// themes.js
export const themes = {
light: {
primary: '#007AFF',
secondary: '#34C759',
danger: '#FF3B30'
},
dark: {
primary: '#0A84FF',
secondary: '#30D158',
danger: '#FF453A'
},
professional: {
primary: '#5856D6',
secondary: '#FF9500',
danger: '#FF2D55'
}
}
使用时动态注入:
function applyTheme(themeName) {
const theme = themes[themeName]
for (const [key, value] of Object.entries(theme)) {
document.documentElement.style.setProperty(`--${key}-color`, value)
}
}
响应式主题切换
监听系统主题变化:
// App.vue
export default {
mounted() {
#ifdef H5
window.matchMedia('(prefers-color-scheme: dark)')
.addEventListener('change', e => {
this.$store.commit('switchTheme', e.matches ? 'dark' : 'light')
})
#endif
}
}
组件库主题适配
处理第三方组件库的主题:
// 修改uView主题
import uView from 'uview-ui'
Vue.use(uView)
function setUViewTheme(theme) {
uni.$u.config.theme = theme === 'dark' ? {
primary: '#0A84FF',
contentBg: '#1C1C1E'
} : {
primary: '#007AFF',
contentBg: '#FFFFFF'
}
}
性能优化建议
- 减少不必要的样式重计算
- 使用 CSS 变量而非直接修改类名
- 对复杂组件使用
v-if
而非v-show
切换 - 预加载主题资源
// 预加载暗色主题图片
uni.preloadImage({
urls: ['/static/dark-bg.jpg', '/static/dark-icon.png']
})
主题切换的用户体验
- 添加切换动画但保持快速响应
- 在设置页面提供主题预览
- 考虑色盲用户的可访问性
- 保持重要元素的对比度
<template>
<view class="theme-preview"
v-for="theme in availableThemes"
:key="theme.name"
:style="{ backgroundColor: theme.colors.background }"
@click="selectTheme(theme.name)">
<text :style="{ color: theme.colors.text }">{{ theme.label }}</text>
</view>
</template>
企业级主题解决方案
大规模应用可采用 CSS-in-JS 方案:
// 使用CSS-in-JS库
import { createUseStyles } from 'react-jss'
const useStyles = createUseStyles({
container: props => ({
backgroundColor: props.theme.background,
color: props.theme.text
})
})
function MyComponent() {
const theme = useTheme() // 从context获取当前主题
const classes = useStyles({ theme })
return <view class={classes.container}>内容</view>
}
动态主题的测试策略
- 自动化测试不同主题下的UI表现
- 验证颜色对比度是否符合WCAG标准
- 测试主题切换时的性能影响
// 测试用例示例
describe('主题切换', () => {
it('应正确应用暗色主题', () => {
store.commit('switchTheme', 'dark')
expect(document.documentElement.className).toContain('dark-theme')
expect(getComputedStyle(document.body).backgroundColor).toBe('rgb(28, 28, 30)')
})
})
主题系统的扩展性设计
- 支持自定义主题上传
- 实现主题属性继承机制
- 建立主题版本控制系统
// 主题合并策略
function mergeThemes(baseTheme, customTheme) {
return {
...baseTheme,
colors: {
...baseTheme.colors,
...customTheme.colors
},
spacing: customTheme.spacing || baseTheme.spacing
}
}
主题切换的辅助功能
确保主题切换不影响可访问性:
<template>
<button
@click="toggleTheme"
aria-label="切换主题"
aria-pressed="isDark"
>
{{ isDark ? '切换到亮色主题' : '切换到暗色主题' }}
</button>
</template>
动态主题的国际化整合
结合多语言实现完整本地化:
// 主题相关文案
const themeMessages = {
en: {
light: 'Light Mode',
dark: 'Dark Mode'
},
zh: {
light: '亮色模式',
dark: '暗色模式'
}
}
主题切换的性能监控
跟踪主题切换相关指标:
// 性能标记
function toggleTheme() {
performance.mark('themeSwitchStart')
// 执行主题切换逻辑
performance.mark('themeSwitchEnd')
performance.measure('themeSwitch', 'themeSwitchStart', 'themeSwitchEnd')
const duration = performance.getEntriesByName('themeSwitch')[0].duration
if (duration > 100) {
reportSlowThemeSwitch(duration)
}
}
本站部分内容来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn