闽公网安备 35020302035485号
<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>
输出结果如下