如何在Vue.js单页应用程序中动态更改主题的最佳方法?

13

所以我认为标题已经足够解释了:我想要动态主题我的整个应用程序。也许这意味着在我按下特定按钮时更改所有 div 的颜色,或者在特定用户登录时更改整个 web 应用程序的颜色。

只是为了给大家一些了解,我将说我已经构建了一个 Vue.js 应用程序,使用了许多库,包括一个名为 Element-ui 的库,它已经内置了一个主题选项。但问题在于它是用 scss 编写的,而我想在导航期间更改所有变量颜色。我的项目看起来像这样:

<template>
  ... some HTML and components...
</template>

<script>
  ... some javascript ...
</script>

<style scoped>
  ... some style that is scoped to the current component only ...
</style>

我有许多类似于这个的文件,所以对于它们所有人都制作一个“全局函数”对我来说似乎不切实际。此外,我只在main.js中导入了主要的scss文件一次。

有什么办法可以为我的Web应用程序创建动态主题?使用Sass是个好主意吗?也许是JavaScript?

编辑

我觉得我没有解释清楚,所以我想添加一个简单的例子。 如果您访问Element页面,则可以看到右上角有一个颜色选择器,当颜色更改时,它也更改整个网站的强调颜色,例如按钮颜色,链接颜色等。

希望这能帮助更好地理解

编辑

现在,我已经选择了一个非常糟糕且我认为优化不良的解决方案。想法是当用户更改主题时,我只需创建一个新的CSS文件并将其附加到当前文档。

let sheet = document.createElement('style')
sheet.innerHTML = `*[class*="--primary"]{
                      background-color: ${colors[0]};
                    }
                    ...`;
document.body.appendChild(sheet);

我真的认为这是一个非常糟糕的解决方案,但现在我想不到其他能够动态工作的东西。我真的希望这个过程是完美的:用户选择一种颜色,整个应用程序就会改变到那个特定的颜色,没有预先构建的 theme.css

最终编辑

我最终找到了一个解决方案,请参考答案!

1个回答

27

经过几个漫长的日子,我找到了一种解决方案,我认为它既容易实现,又非常轻量级。

CSS变量

在进行大量搜索之前,我甚至不知道这种变量的存在,它们似乎并不常用。无论如何,我希望这可以帮助寻找与我相同答案的人:

<template
  <app-main></app-main>
  <app-sidebar></app-sidebar>
  ...
</template>

<style>
  :root{
    --primary-color: #C5C5C5!important;
    --secondary-color: #6C7478!important;
    --tertiary-color: #FFFFFF!important;
    --success-color: #80b855!important;
    --warning-color: #eaca44!important;
    --error-color: #ef4d4d!important;
  }

  /* Theming */
  header{
    background-color: var(--primary-color);
  }
  div{
    color: var(--tetriary-colory);
  }
  ...
  /*   END   */
</style>

<script>
  import axios from 'axios' /* all your imports etc. */

  export default{
    data(){
    },
    methods: {
      axios.post(`http://localhost:8080/foo`).then(function (response){
        let bodyStyles = document.body.style;
        bodyStyles.setProperty('--primary-color', response.colors[0]);
        bodyStyles.setProperty('--tertiary-color', response.colors[1]);
        ...
      }
    }
  }
</script>

如您所见,我初始化了一些有用的CSS变量,当我需要它们时(例如在该API POST调用中),我只需使用简单的bodyStyles.setProperty('propertyName')函数进行修改。

我非常喜欢这种设置方式,因为我在登录页中使用它,所以当用户成功登录时,我从数据库中加载他自己的颜色并像这样设置它们。

我的网站示例

希望这可以帮助某些人!干杯!


3
这在IE11及更旧版本中无法工作。为了实现即时主题更改,我使用vuex + :style{color: primary}等方法。https://codesandbox.io/s/3no663nv6 - DenniLa2
@DenniLa2 对不起晚回复,但你说得完全正确,最佳实践是开始使用 vuex,但出于时间和简单起见,我选择了这种实现方式。 - Eugenio
1
但是 Element UI 没有读取 CSS 变量,所以它无法用于 Element UI 或其他 UI 框架。 - sangelee
@sangelee,你在element-ui中找到如何做这个了吗? - linx

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接