Vue与Bootstrap Vue中如何通过data属性配合SCSS变量实现主题切换
核心原因
你之前的写法不生效是因为SCSS变量属于预编译变量,仅在代码编译阶段生效,打包后会被替换为固定的色值,所以嵌套在[data-theme="dark"]选择器内重新声明SCSS变量的写法,不会在运行时动态作用到对应组件上。
最简实现方案
不需要逐个选中组件类名调整,用「根节点挂载主题属性+CSS原生变量」的方案可以实现全局主题一键切换,步骤如下:
全局挂载主题属性
不需要给每个组件单独绑定data-theme、引入vuex状态,直接将主题属性挂到页面根节点(html标签)即可:
在App.vue中监听vuex的theme状态变化,同步更新根节点属性:
import { mapState } from 'vuex' export default { computed: { ...mapState(['theme']) }, watch: { theme(newVal) { document.documentElement.dataset.theme = newVal localStorage.setItem('theme', newVal) } }, mounted() { document.documentElement.dataset.theme = this.theme } }
后续所有组件都不需要再处理theme相关的状态引入、属性绑定逻辑。
全局统一定义主题变量
放弃用SCSS变量做动态主题切换,改为用CSS原生变量统一定义所有主题色值,在custom.scss中全局声明:
// 基础色值可以继续用SCSS变量管理 $light-breadcrumb-bg: #f5f5f5; $dark-breadcrumb-bg: #2d2d2d; $light-page-bg: #ffffff; $dark-page-bg: #121212; // 所有组件需要用到的主题色都可以在这里提前定义 :root { // 亮色模式默认变量值 --breadcrumb-bg: #{$light-breadcrumb-bg}; --page-bg: #{$light-page-bg}; // 新增其他主题变量直接在这里加即可 } [data-theme="dark"] { // 暗色模式统一覆盖所有变量值 --breadcrumb-bg: #{$dark-breadcrumb-bg}; --page-bg: #{$dark-page-bg}; }
组件内直接调用变量
所有组件的样式不需要单独适配暗色模式,直接调用定义好的原生变量即可:
.breadcrumb { background-color: var(--breadcrumb-bg); } // 其他组件同理,直接用对应的变量,不需要再写[data-theme]判断
如果是使用第三方UI库,也可以全局覆盖UI库的默认样式变量,将其值替换为你定义的CSS原生变量,一次配置全库生效。
内容的提问来源于stack exchange,提问作者Bruno Werneck
相关产品推荐
相关产品推荐

