Sass 子组件的上下文或基于状态的重写的最佳实践
我将样式表分解为表示单个组件(nav、nav项等)。我试图理解允许家长基于其状态或上下文覆盖子样式的最佳方式(在导航打开时更改导航项,在主页上更改导航项,等等) 例如,假设我有一个包含导航项目的导航。它们被分为各自的样式表nav.scss和nav-item.scss。当.nav组件添加了.open类时,我想使.nav项背景变成红色。我可以这样做:Sass 子组件的上下文或基于状态的重写的最佳实践,sass,Sass,我将样式表分解为表示单个组件(nav、nav项等)。我试图理解允许家长基于其状态或上下文覆盖子样式的最佳方式(在导航打开时更改导航项,在主页上更改导航项,等等) 例如,假设我有一个包含导航项目的导航。它们被分为各自的样式表nav.scss和nav-item.scss。当.nav组件添加了.open类时,我想使.nav项背景变成红色。我可以这样做: /* nav.scss */ @import nav-item.scss .nav{ &.open{ .nav-ite
/* nav.scss */
@import nav-item.scss
.nav{
&.open{
.nav-item{
background: red;
}
}
}
/* nav-item.scss */
.nav-item{
background: blue;
}
这很好,但现在应用于.nav项的样式被应用于.nav项样式表之外,如果在多个位置发生这种情况,则很难跟踪哪个文件正在向.nav项添加哪些样式。另一种选择是:
/* nav.scss */
@import nav-item.scss
.nav{
}
/* nav-item.scss */
.nav-item{
background: blue;
.nav.open &{
background: red;
}
}
此语法允许我访问父树,查看是否嵌套在.nav.open中,然后应用红色背景。这很好,因为所有导航项目样式现在都包含在同一个文件中,因此更容易查看所有可能的样式。但是,我仍然引用了一个外部类,这似乎是错误的,另外,如果我有很多变体,这个文件可能会很快变得糟糕:
/* nav-item.scss */
.nav-item{
background: blue;
.nav.open &{
background: red;
}
.nav.sticky.open &{
background: blue;
}
.homepage .nav.open &{
@media screen and (max-width: $break-small) {
background: green;
}
}
}
我们可以尝试使用mixin:
/* nav.scss */
@import nav-item.scss
.nav{
&.open{
@include navItemRedWide();
}
}
/* nav-item.scss */
.nav-item{
background: blue;
}
@mixin navItemRedWide() {
.nav-item {
background: red;
width: 400px;
}
}
这有效地允许nav-item.scs包含它自己的所有样式,并允许.nav指定要应用的样式,而无需直接在类上添加/修改样式属性。这似乎比其他解决方案更好,但如果我必须在每个混合中重复嵌套,可能会导致大量混合,并可能导致大量重复代码:
/* nav-item.scss */
@mixin navItemLargeIcon() {
.nav-item {
.inner{
.icon{
font-size: 4rem;
}
}
}
}
@mixin navItemSmallIcon() {
.nav-item {
.inner{
.icon{
font-size: 1rem;
}
}
}
}
最后,如果有一个子组件的子组件需要从中提取mixin,那么这个问题就更加复杂了:
/* nav.scss */
@import nav-panel.scss
@import nav-item.scss
.nav{
&.open{
@include navItemRed();
@include navPanelRed();
}
}
/* nav-panel.scss */
@import nav-item.scss
.nav-panel{
background: blue;
&.collapse{
@include navPanelBlue();
}
}
@mixin navPanelRed() {
.nav-panel {
background: red;
}
}
/* nav-item.scss */
.nav-item{
background: blue;
}
@mixin navItemRed() {
.nav-item {
background: red;
}
}
@mixin navItemBlue() {
.nav-item {
background: red;
}
}
现在我有根文件导入子对象的子对象只是为了应用它们的mixin,而中间的子对象也在导入子对象,并可能应用覆盖的mixin,而while的东西就变成了不可维护的混乱
应用这些基于上下文或状态的样式和子组件重写的最佳实践是什么?正如您所描述的,在SCS中有很多处理上下文的方法,但如果我必须选择一种,它将是基于混合的
// -----------------------------
// _nav.scss
// -----------------------------
// Base styling
@mixin nav {
.nav {
...
}
}
// Context overrides/add-ons
// note! keep context overrides in the component scss - it makes
// it easier to track and provides an overview of variations
@mixin nav-context-1 { .context-1 .nav { ... } }
@mixin nav-context-2 { .context-2 .nav { ... } }
@mixin nav-context-3 { .context-3 .nav { ... } }
使用mixin(用于一切)可以预测最终CSS中打印的内容作为编译样式。SCS将只包含导入和包含(汇编)
同样,没有一个答案——但我发现上面的答案是最有条理、最容易处理的
PS.对上述内容稍加修改,可以使上下文混合依赖于nav作为包装包含。这样,如果您试图在不存在基础的情况下包含覆盖,Sass将抛出错误
@mixin nav {
.nav {
...
@content; // contexts will go here
}
}
// note! we use & in the selector to disallow include at root level
@mixin nav-context-1 { .context-1 & { ... } }
@mixin nav-context-2 { .context-2 & { ... } }
@mixin nav-context-3 { .context-3 & { ... } }
// Assemble
@include nav {
@include nav-context-1;
@include nav-context-2;
@include nav-context-3;
}
@include nav-context-3; // this will throw an error
@mixin nav {
.nav {
...
@content; // contexts will go here
}
}
// note! we use & in the selector to disallow include at root level
@mixin nav-context-1 { .context-1 & { ... } }
@mixin nav-context-2 { .context-2 & { ... } }
@mixin nav-context-3 { .context-3 & { ... } }
// Assemble
@include nav {
@include nav-context-1;
@include nav-context-2;
@include nav-context-3;
}
@include nav-context-3; // this will throw an error