<main className="sample-page"> <h1>With Scope</h1> <section className="first-section"> <p>some text</p> <p> some text and then a <a href="/">back link</a> </p> </section> <section className="second-section"> <h2>Dog Picture</h2> <div> <p>second section paragraph text</p> </div> <img src={'./DOG_1.jpg'} alt="dog" /> </section> </main>在此 HTML 中,我们可以使用以下方法对 second-section 样式区域内的元素进行样式设置:
.second-section { display: flex; flex-direction: column; border: solid; padding: 40px; margin: 20px; } @scope (.second-section) { h2 { text-align: center; } img { max-width: 400px; max-height: 100%; } div { display: flex; justify-content: center; margin: 20px; } p { max-width: 200px; text-align: center; background-color: pink; color: forestgreen; padding: 10px; border-radius: 20px; font-size: 24px; } }使用 @scope 时,还可以创建一个 "甜甜圈 "作用域,为一组样式及其中的元素定义起始和结束部分。使用上述相同的 HTML,甜甜圈作用域可以定义从 sample-page 的起始区域到 second-section 样式区域的样式:
/* donut scope */ @scope (.sample-page) to (.second-section) { p { font-size: 24px; background-color: forestgreen; color: pink; text-align: center; padding: 10px; } a { color: red; font-size: 28px; text-transform: uppercase; } }最棒的是,它的功能与使用 BEM 造型非常相似,但代码量更少。
<main className="sample-page"> <h1 className="sample-page__title">With BEM</h1> <section className="sample-page__first-section"> <p className="sample-page__first-section--first_line"> some text </p> <p className="sample-page__first-section--second-line"> some text and then a{' '} <a className="sample-page__first-section--second-line-link" href="/" > back link </a> </p> </section> </main>在此 HTML 中:
.元素 = 在为 <h1> 元素设计样式时,该元素被视为 element ,因此会在样式名称中添加额外的 __ ,从而创建 sample-page__title 。 sample-page__first-section 也是如此。
.sample-page { display: flex; flex-direction: column; margin-top: 10px; &__title { font-size: 48px; color: forestgreen; } &__first-section { font-size: 24px; border: solid; padding: 40px; margin: 20px; &--first-line{ font-size: 24px; background-color: forestgreen; color: pink; text-align: center; padding: 10px; } } }难点在于,在一个大型项目中,这会产生非常大的 CSS 或 SASS 文件,而这些文件仍然很难进行大规模管理。可以使用 @scope 替换 BEM 样式,使样式定义更小、更易于管理。
<main className="sample-page"> <h1 className="sample-page__title">With BEM</h1> <section className="sample-page__first-section"> <p className="sample-page__first-section--first_line"> some text </p> <p className="sample-page__first-section--second-line"> some text and then a{' '} <a className="sample-page__first-section--second-line-link" href="/" > back link </a> </p> </section> <section className="sample-page__second-section"> <h2 className="sample-page__second-section--title"> Dog Picture </h2> <div className="sample-page__second-section--div"> <p className="sample-page__second-section--div-paragraph"> second section paragraph text </p> </div> <img className="sample-page__second-section--image" src={'./DOG_1.jpg'} alt="dog" /> </section> </main>在组件 WithScopePage.tsx 中,我们可以通过以下内容看到重构是多么干净利落:
<main className="sample-page"> <h1>With Scope</h1> <section className="first-section"> <p>some text</p> <p> some text and then a <a href="/">back link</a> </p> </section> <section className="second-section"> <h2>Dog Picture</h2> <div> <p>second section paragraph text</p> </div> <img src={'./DOG_1.jpg'} alt="dog" /> </section> </main>要将 BEM 重构为 @scope ,只需找到样式组,然后适当添加您的作用域样式。我们先来看看标题部分。在原始的 WithBEMPage.tsx 文件中,每个部分都定义了不同的样式。而在 @scope 版本中,则为特定元素定义了更简洁的样式:
.sample-page { display: flex; flex-direction: column; margin-top: 10px; } /* replaced */ /* .sample-page__title { font-size: 48px; color: forestgreen; } */ /* donut scope */ @scope (.sample-page) to (.first-section) { h1 { font-size: 48px; color: forestgreen; } }同样,在第一部分内容中,原始 BEM 风格如下:
.sample-page__first-section { font-size: 24px; border: solid; padding: 40px; margin: 20px; } .sample-page__first-section--first_line { font-size: 24px; background-color: forestgreen; color: pink; text-align: center; padding: 10px; } .sample-page__first-section--second-line { font-size: 24px; background-color: forestgreen; color: pink; text-align: center; padding: 10px; } .sample-page__first-section--second-line-link { color: red; font-size: 28px; text-transform: uppercase; }用 @scope 重构第一部分,我们现在就有了一个更简洁的样式定义:
.first-section { font-size: 24px; border: solid; padding: 40px; margin: 20px; } /* donut scope */ @scope (.sample-page) to (.second-section) { p { font-size: 24px; background-color: forestgreen; color: pink; text-align: center; padding: 10px; } a { color: red; font-size: 28px; text-transform: uppercase; } }这样做的另一个好处是,HTML 视图更小,更容易阅读。考虑到之前
<section className="sample-page__first-section"> <p className="sample-page__first-section--first_line"> some text </p> <p className="sample-page__first-section--second-line"> some text and then a{' '} <a className="sample-page__first-section--second-line-link" href="/" > back link </a> </p> </section>然后
<section className="first-section"> <p>some text</p> <p> some text and then a <a href="/">back link</a> </p> </section>通过这两个示例组件,我们可以对每个部分进行重构。最终注意到它是如何使样式更简洁、更易读的。
<!DOCTYPE html> <html> <head> <title>堆代码 duidaima.com</title> <style> .light { background: #ccc; } .dark { background: #333; } .light a { color: red; } .dark a { color: yellow; } div { padding: 2rem; } div > div { margin: 0 0 0 2rem; } p { margin: 0 0 2rem 0; } </style> </head> <body> <div class="light"> <p><a href="#">First Level</a></p> <div class="dark"> <p><a href="#">Second Level</a></p> <div class="light"> <p><a href="#">Third Level</a></p> </div> </div> </div> </body> </html>结果如下:
<!DOCTYPE html> <html> <head> <title>Plain HTML</title> <style> .light { background: #ccc; } .dark { background: #333; } div { padding: 2rem; } div > div { margin: 0 0 0 2rem; } p { margin: 0 0 2rem 0; } @scope (.light) { :scope { background: white; } a { color: red; } } @scope (.dark) { :scope { background: black; } a { color: yellow; } } </style> </head> <body> <div class="light"> <p><a href="#">First Level</a></p> <div class="dark"> <p><a href="#">Second Level</a></p> <div class="light"> <p><a href="#">Third Level</a></p> </div> </div> </div> </body> </html>输出结果如下