在加载时切换 Vue3 主题/CSS 文件并单击

Switch Vue3 theme / CSS file on load and click

包含主题的推荐方法是在应用根目录下的 main.js 文件中导入:

import 'primevue/resources/themes/arya-orange/theme.css';

但我正在寻找一种方法来根据用户系统主题和用户选择来切换 CSS 文件,所以我将其移到了我的主 App.vue:

export default {
  name: "App",
  components: {
    HelloWorld,
    toDo,
  },
  mounted() {

    //window.matchMedia('(prefers-color-scheme: dark)').matches ? do dark : do light
  },
};

<style>
@media (prefers-color-scheme: dark) {
  @import url("primevue/resources/themes/bootstrap4-dark-blue/theme.css");
}
@media (prefers-color-scheme: light) {
  @import url("primevue/resources/themes/bootstrap4-light-blue/theme.css");
}
</style>

我无法在 mounted 和 styles 标签中导入任何内容我也无法在 media 中导入,这两种用法都不正确。

我在网上找不到任何其他方法或指导来解决这个问题。所有解决方案都基于范围组件,使用 类 等

我可以将所有规则包装在一个主题中以

@media (prefers-color-scheme: dark) {

还有一个用于照明。但是话又说回来,我怎样才能打开用户选择?

编辑:

我找到了一种让它在负载下工作的方法:

(async () => {
  if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
    await import('primevue/resources/themes/bootstrap4-dark-blue/theme.css');
  }else {
    await import('primevue/resources/themes/bootstrap4-light-blue/theme.css');
  }
})();

并在点击时覆盖第一次导入:

  methods: {
    theme() {
      (async () => {
          await import("primevue/resources/themes/bootstrap4-light-blue/theme.css");
      })();
    },
  },

但是 当我尝试使用单击将其切换回来时它什么也没做,我的猜测是因为如果系统是黑暗的,它会在第一次导入时加载黑暗主题,然后再导入点击它加载浅色主题,但之后它不会在点击时切换回深色,我的猜测是因为深色已经准备好加载并且它不会在切换时生效。

请指教

一种解决方案是像在 PrimeVue 网站上那样实施。总之,css 主题是使用 index.html 文件中的 link 导入的:

<!DOCTYPE html>
<html lang="en">
    <head>
...
<link id="theme-link" rel="stylesheet" href="<%= BASE_URL %>themes/saga-blue/theme.css">
    </head>
    <body>
...
    </body>
</html>

有关示例,请参阅 this link

然后要切换主题,可以这样实现:

changeTheme(event) {
    let themeElement = document.getElementById('theme-link');
    themeElement.setAttribute('href', themeElement.getAttribute('href').replace(this.theme, event.theme));
    this.theme = event.theme;
    this.activeMenuIndex = null;
    EventBus.emit('change-theme', event);
    this.$appState.darkTheme = event.dark;
    if (event.theme.startsWith('md')) {
        this.$primevue.config.ripple = true;
    }
    localStorage.setItem('theme', this.theme);
}

这是 PrimeVue 文档中的实现方式。参见 here