使用css变量实现微信小程序主题色切换

场景说明:管理员可在管理后台配置自定义颜色为主题色,小程序无需打包进行切换

1. 介绍一下CSS自定义属性(变量):

css变量的基本使用方式:

// css变量定义
:root {
	--background-color:#fff;
	--text-color:#333;
}
// var方法第一个参数是变量名,第二个为备用参数,在第一个变量失效的时候生效,
// 其他复杂使用方式可以查看文档
h1 {
	background-color: var(--background-color,'#fff');
	color: var(--text-color,#333);
}

注意,规则集所指定的选择器定义了自定义属性的可见作用域。通常的最佳实践是定义在根伪类 :root 下,这样就可以在 HTML 文档的任何地方访问到它了。

2. 这里以普通HTML为例,实现主题色切换

通过给html标签动态设置style实现主题切换。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    :root {
      --background-color: #fff;
      --text-color: #333;
    }
    h1 {
      background-color: var(--background-color,'#fff');
      color: var(--text-color,#333);
    }
  </style>
</head>
<body>
  <div>
    <h1>Hello World</h1>
    <ul>
      <li data-color="red">主题红色</li>
      <li data-color="blue">主题蓝色</li>
    </ul>
  </div>
  <script>
    const ul = document.querySelector('ul');
    ul.onclick = (event) => {
      const target = event.target;
      if (target.tagName.toLowerCase() === 'li') {
        document.documentElement.style.setProperty('--background-color', target.dataset.color);
        document.documentElement.style.setProperty('--text-color', '#fff');
      }
    }
  </script>
</body>
</html>

3. 小程序实现:

思路和普通的html一样,给根节点style设置变量,但小程序存在一个问题无法动态给Page节点设置style。为了解决这个问题,我们只能自定义第一个页面容器。首次加载小程序的时候,从服务器获取配置,通过redux进行theme更新,实现主题色的动态切换。

4. 用taro的redux模版实现demo

taro init 初始化一个redux模版,在store里添加一个getConfig方法获取主题数据

// 修改路径store/index文件
const getConfig = async(dispatch) => {
  const getTheme = async() => {
    return new Promise((resolve) => {
    	// 模拟数据获取,真实场景使用真实api获取数据
      setTimeout(() => {
        resolve({
          'backgroundColor': 'red',
          'textColor': '#fff'
        });
      },1000);
    })
  }
  const theme = await getTheme();
  
  if (theme) {
    dispatch({
      type: "SET_THEME",
      payload: {
        ...theme,
      }
    })
  }
}

export default function configStore () {
  const store = createStore(rootReducer, enhancer)
  // 获取配置
  getConfig(store.dispatch);

  return store
}

注意:这里还需要修改reducers为自己需要处理的type,这里就不再赘述。具体可以查看源码。

有了主题数据,我们还需要实现一个页面容器Page组件,作为css变量设置的节点,以下组建Page/index.tsx

import { View } from '@tarojs/components';
import { useSelector } from 'react-redux';
import { useMemo } from 'react';
import './index.less';

type Theme = {
  backgroundColor: string;
  textColor: string;
}

const Page = ({ children }) => {
  const theme = useSelector((state: { theme: Theme }) => state.theme);

  console.log('主题:', theme)
  const styles = useMemo(() => {
    if (theme) {
      return {
        '--background-color': theme.backgroundColor,
        '--text-color':theme.textColor
      }
    }
    return null;
  }, [theme]);

  return (
    <View style={styles} className="page">
      {children}
    </View>
  )
}

export default Page;

Page组件的样式:

.page {
  width: 100vw;
  height: 100vh;
  box-sizing: border-box;
  overflow: auto;
}

有了Page组建我们在每个页面最外层套上即可。效果如下(视频转换失效,放个图片):
在这里插入图片描述

5. 源码下载:

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值