可切换 Vaadin 12 主题的最佳实践
Best practice for switchable Vaadin 12 themes
我目前正在将 Vaadin 8 应用程序迁移到 Vaadin 12。外观应该由用户使用,并在登录时或通过按下按钮进行更改。
在我们的 Vaadin 8 应用程序中,我们有 2 个主题(深色和浅色),每个主题都有自己的 SASS/CSS 和一些共享属性。用户可以使用 setTheme() 方法来切换它。当点击切换按钮时,外观和感觉就发生了变化。在 Vaadin 12 中,主题采用不同的方法,我正在努力寻找一种在 Vaadin 12 中实现此功能的好方法。
假设我们不想创建一个全新的主题,只想使用自定义的 LUMO。我可以通过@Theme 注释设置Theme/Variant。缺点:主题将在运行时修复。
我也可以编写一些代码来将变体应用于我的应用程序和组件。 (就像在动态样式章节中: https://vaadin.com/docs/flow/element-api/tutorial-dynamic-styling.html )
缺点:遍历每个元素并应用变体不是很可行。
我现在的问题:
在运行时实现主题之间切换的最佳方法是什么?(Lumo 或任何其他主题的自定义明暗变体)。
我是否会创建 2 个包含 CSS 的 HTML 文件(为了兼容性),然后通过动态导入以某种方式覆盖当前使用的文件?
我希望我的问题很清楚,有人可以指出正确的方向。
在同一主题的两个不同变体之间切换相对容易,例如Lumo 的深色和浅色变体。为此,您只需切换 <html>
元素上相应的 theme
属性。无法从服务器直接访问该元素,但您可以使用一小段 JavaScript: ui.getPage().executeJavaScript("document.documentElement.setAttribute([=12=], )", "theme", "dark");
根据具体情况,您可以或必须将更改应用于 <body>
元素。在这种情况下,您可以在 JS 片段中将 .documentElement
切换为 .body
,或者直接在 Java.
中使用 ui.getElement().setAttribute("theme", "dark")
在两个不同的基本主题之间切换,例如Lumo vs Material 是一件复杂得多的事情。对于每个组件,浏览器中只能同时加载一个基本主题,重新加载页面是摆脱已经加载的唯一方法。对于用于 Flow 的每个组件,除了没有任何样式的基本导入之外,框架还负责加载正确的主题导入。更复杂的是,使用 @Theme
指定的主题自动包含在应用程序的生产包中。为了能够使用多个基本主题,您还必须以某种方式生成多个不同的捆绑包,并以某种方式配置 Flow 以根据情况使用正确的捆绑包。
如果您只想在亮和暗之间切换,那么您可以add/remove dark
在 DOM 的一个很高的地方。例如。 UI 的元素通常是 body
或至少非常高。
例如:
new Checkbox("Use Dark Theme").tap{
addValueChangeListener{ cb ->
getUI().ifPresent(){ ui ->
def themeList = ui.getElement().getThemeList()
if (cb.value) {
themeList.add(Lumo.DARK)
} else {
themeList.remove(Lumo.DARK)
}
}
}
}
编辑
正如另一个答案的评论中所问:
要更改主题中的颜色,您可以覆盖使用的颜色。这是如何更改浅色和深色 Lumo 主题的文本颜色的示例:
html {
--lumo-body-text-color: red;
}
[theme~="dark"] {
--lumo-body-text-color: yellow;
}
我目前正在将 Vaadin 8 应用程序迁移到 Vaadin 12。外观应该由用户使用,并在登录时或通过按下按钮进行更改。
在我们的 Vaadin 8 应用程序中,我们有 2 个主题(深色和浅色),每个主题都有自己的 SASS/CSS 和一些共享属性。用户可以使用 setTheme() 方法来切换它。当点击切换按钮时,外观和感觉就发生了变化。在 Vaadin 12 中,主题采用不同的方法,我正在努力寻找一种在 Vaadin 12 中实现此功能的好方法。
假设我们不想创建一个全新的主题,只想使用自定义的 LUMO。我可以通过@Theme 注释设置Theme/Variant。缺点:主题将在运行时修复。
我也可以编写一些代码来将变体应用于我的应用程序和组件。 (就像在动态样式章节中: https://vaadin.com/docs/flow/element-api/tutorial-dynamic-styling.html ) 缺点:遍历每个元素并应用变体不是很可行。
我现在的问题:
在运行时实现主题之间切换的最佳方法是什么?(Lumo 或任何其他主题的自定义明暗变体)。
我是否会创建 2 个包含 CSS 的 HTML 文件(为了兼容性),然后通过动态导入以某种方式覆盖当前使用的文件?
我希望我的问题很清楚,有人可以指出正确的方向。
在同一主题的两个不同变体之间切换相对容易,例如Lumo 的深色和浅色变体。为此,您只需切换 <html>
元素上相应的 theme
属性。无法从服务器直接访问该元素,但您可以使用一小段 JavaScript: ui.getPage().executeJavaScript("document.documentElement.setAttribute([=12=], )", "theme", "dark");
根据具体情况,您可以或必须将更改应用于 <body>
元素。在这种情况下,您可以在 JS 片段中将 .documentElement
切换为 .body
,或者直接在 Java.
ui.getElement().setAttribute("theme", "dark")
在两个不同的基本主题之间切换,例如Lumo vs Material 是一件复杂得多的事情。对于每个组件,浏览器中只能同时加载一个基本主题,重新加载页面是摆脱已经加载的唯一方法。对于用于 Flow 的每个组件,除了没有任何样式的基本导入之外,框架还负责加载正确的主题导入。更复杂的是,使用 @Theme
指定的主题自动包含在应用程序的生产包中。为了能够使用多个基本主题,您还必须以某种方式生成多个不同的捆绑包,并以某种方式配置 Flow 以根据情况使用正确的捆绑包。
如果您只想在亮和暗之间切换,那么您可以add/remove dark
在 DOM 的一个很高的地方。例如。 UI 的元素通常是 body
或至少非常高。
例如:
new Checkbox("Use Dark Theme").tap{
addValueChangeListener{ cb ->
getUI().ifPresent(){ ui ->
def themeList = ui.getElement().getThemeList()
if (cb.value) {
themeList.add(Lumo.DARK)
} else {
themeList.remove(Lumo.DARK)
}
}
}
}
编辑
正如另一个答案的评论中所问:
要更改主题中的颜色,您可以覆盖使用的颜色。这是如何更改浅色和深色 Lumo 主题的文本颜色的示例:
html {
--lumo-body-text-color: red;
}
[theme~="dark"] {
--lumo-body-text-color: yellow;
}