为什么 css 样式在 react.js 中使用相同的 class 名称时会从组件中泄漏(被其他组件继承)?
Why css styles leaks (gets inherited by other components) out of the component when they use the same class names in react.js?
我在 'create react app' 中创建了两个独立的组件。对于每个组件,我都有专门的样式 sheet。如果我在两个组件中使用相同的类名,那么样式也会继承到另一个组件。
在这里,在我的例子中,即使我将 Quote.scss 文件保留为空,样式也会从 Contact 组件的 contact.css 文件继承。
在这里,您可以看到我没有在 Quote.jsx 文件中导入 Contact.css 样式 sheet。
有什么方法可以避免它,同时仍然在不同的组件中使用相同的类名?
我项目里面的文件夹结构-
ContactPage
Contact.jsx
Contact.scss
Contact.css
QuotePage
Quote.jsx
Quote.scss
Quote.css
Contact.jsx 文件-
import "./Contact.css";
import React, {useState} from 'react';
import axios from "axios";
<div className="form">
<div className='container'>
<div className="input-row">
<div className="block">
<label>First Name</label>
<input className="input" type="text" name="fName" onChange={handleChange} value={postData.fName} />
</div>
<div className="block">
<label >Last Name</label>
<input className="input" type="text" name="lName" onChange={handleChange} value={postData.lName}/>
</div>
</div>
<div className="input-row">
<div className="block">
<label>Email</label>
<input className="input is-success" type="email" name="email" onChange={handleChange} value={postData.email}/>
</div>
<div className="block">
<label >Phone</label>
<input className="input" type="tel" name="phone" onChange={handleChange} value={postData.phone}/>
</div>
</div>
<div className="textarea-row">
<div className="block">
<label >Message</label>
<textarea className="textarea" name="message" onChange={handleChange} value={postData.message}></textarea>
</div>
</div>
{/* row-3 */}
<div className="btn-row">
<button className="submit-btn" onClick={handleSubmit}>Submit</button>
<button className="cancel-btn" onClick={handleCancel}>Cancel</button>
</div>
<div className='submit-message'>
<h1>{message}</h1>
</div>
</div>
</div>
我的Contact.scss文件-
@mixin section {
padding: 4rem 0;
height: auto;
}
@mixin container {
width: auto;
height: auto;
max-width:1100px;
padding: 0 40px;
margin: 0 auto;
align-items:center;
@media screen and (max-width:768px){
grid-template-columns: 1fr;
grid-gap: 1rem;
width: auto;
height: auto;
max-width:none;
padding: 0 40px;
margin: 0 auto;
align-items:none;
}
}
label{
font-weight: 400;
}
.form{
@include section;
.container{
@include container;
display: grid;
grid-template-rows: auto auto auto auto;
grid-row-gap: 2rem;
.input-row{
display: grid;
grid-template-columns: 1fr 1fr;
grid-gap: 1rem;
input{
padding-left: 1rem;
height: 2.5rem;
outline: coral solid 1px;
border: none;
font-size: 1.2rem;
font-weight: 100;
&:focus {
outline: #0b5a68 solid 1px;
border: none;
box-shadow: 0 0 4px #0b5a68;
}
}
@media screen and (max-width:768px){
grid-template-columns: 1fr;
align-self: center;
justify-content: center;
}
.block{
display: grid;
grid-template-rows: auto auto;
grid-gap:.25rem;
}
}
.textarea-row{
@media screen and (max-width:768px){
grid-template-columns: auto;
align-self: center;
justify-content: center;
}
.block{
display: grid;
grid-template-rows: auto auto;
grid-gap:.25rem;
@media screen and (max-width:768px){
grid-template-columns: 1fr;
align-self: center;
justify-content: center;
}
textarea{
padding-left: 1rem;
height: 2.5rem;
outline: coral solid 1px;
border: none;
&:focus {
outline: #0b5a68 solid 1px;
box-shadow: 1px 1px 20px #0b5a68;
border: none;
box-shadow: 0 0 4px #0b5a68;
}
height: 4rem;
padding: 1rem 0 0 1rem;
font-size: 1.2rem;
font-weight: 100;
}
}
}
.btn-row{
display: grid;
grid-template-columns: 1fr 1fr 1fr 1fr;
grid-gap:1rem;
@media screen and (max-width:768px){
grid-template-columns: auto;
align-self: center;
justify-content: center;
grid-template-columns: 1fr 1fr;
}
.submit-btn{
display: grid;
justify-content: center;
align-items: center;
width: 100%;
color: white;
background-color: #108397;
border: solid #108397 2px;
border-radius: 4px;
padding: 1rem 1rem;
text-decoration: none;
font-size: 1rem;
font-weight: 600;
outline: none;
&:hover{
background-color: #0b5a68;
border: solid #0b5a68 2px;
transition: ease .3s;
}
}
.cancel-btn{
display: grid;
justify-content: center;
align-items: center;
width: 100%;
color: white;
background-color: #df60b5c7;
border: solid #df60b59c 2px;
border-radius: 4px;
padding: 1rem 1rem;
text-decoration: none;
font-size: 1rem;
font-weight: 600;
outline: none;
&:hover{
background-color: #b4348a;
border: solid #b4348a 2px;
transition: ease .3s;
}
}
}
}
}
我的Quote.jsx文件-
import './Quote.css';
import React, { useState } from 'react';
import axios from 'axios';
<div className="form">
<div className='container'>
<fieldset className='preference'>
<legend>Select your preference</legend>
<div className="preference-row">
<input className="check" checked={radio==="short-term-use"} onChange={e=>setRadio(e.target.value)} type="radio" name="shortTermUse" value="short-term-use" />
<label for="short-term-use">Short Term Use</label>
</div>
<div className="preference-row">
<input className="check" checked={radio==="long-term-use"} onChange={e=>setRadio(e.target.value)} type="radio" name="longTermUse" value="long-term-use" />
<label for="long-term-use">Long Term Use</label>
</div>
</fieldset>
<div className="btn-row">
<button className="submit-btn" onClick={handleSubmit}>Submit</button>
<button className="cancel-btn" onClick={handleCancel}>Cancel</button>
</div>
</div>
</div>
我的Quote.scss文件-
// it's empty
React 默认没有 class 封装,如果你想实现 CSS 风格的封装
,你可以阅读 this article 关于你的选项
另见@Jacob Smit 在下面的评论中提到的CSS modules。
我在 'create react app' 中创建了两个独立的组件。对于每个组件,我都有专门的样式 sheet。如果我在两个组件中使用相同的类名,那么样式也会继承到另一个组件。
在这里,在我的例子中,即使我将 Quote.scss 文件保留为空,样式也会从 Contact 组件的 contact.css 文件继承。
在这里,您可以看到我没有在 Quote.jsx 文件中导入 Contact.css 样式 sheet。
有什么方法可以避免它,同时仍然在不同的组件中使用相同的类名?
我项目里面的文件夹结构-
ContactPage
Contact.jsx
Contact.scss
Contact.css
QuotePage
Quote.jsx
Quote.scss
Quote.css
Contact.jsx 文件-
import "./Contact.css";
import React, {useState} from 'react';
import axios from "axios";
<div className="form">
<div className='container'>
<div className="input-row">
<div className="block">
<label>First Name</label>
<input className="input" type="text" name="fName" onChange={handleChange} value={postData.fName} />
</div>
<div className="block">
<label >Last Name</label>
<input className="input" type="text" name="lName" onChange={handleChange} value={postData.lName}/>
</div>
</div>
<div className="input-row">
<div className="block">
<label>Email</label>
<input className="input is-success" type="email" name="email" onChange={handleChange} value={postData.email}/>
</div>
<div className="block">
<label >Phone</label>
<input className="input" type="tel" name="phone" onChange={handleChange} value={postData.phone}/>
</div>
</div>
<div className="textarea-row">
<div className="block">
<label >Message</label>
<textarea className="textarea" name="message" onChange={handleChange} value={postData.message}></textarea>
</div>
</div>
{/* row-3 */}
<div className="btn-row">
<button className="submit-btn" onClick={handleSubmit}>Submit</button>
<button className="cancel-btn" onClick={handleCancel}>Cancel</button>
</div>
<div className='submit-message'>
<h1>{message}</h1>
</div>
</div>
</div>
我的Contact.scss文件-
@mixin section {
padding: 4rem 0;
height: auto;
}
@mixin container {
width: auto;
height: auto;
max-width:1100px;
padding: 0 40px;
margin: 0 auto;
align-items:center;
@media screen and (max-width:768px){
grid-template-columns: 1fr;
grid-gap: 1rem;
width: auto;
height: auto;
max-width:none;
padding: 0 40px;
margin: 0 auto;
align-items:none;
}
}
label{
font-weight: 400;
}
.form{
@include section;
.container{
@include container;
display: grid;
grid-template-rows: auto auto auto auto;
grid-row-gap: 2rem;
.input-row{
display: grid;
grid-template-columns: 1fr 1fr;
grid-gap: 1rem;
input{
padding-left: 1rem;
height: 2.5rem;
outline: coral solid 1px;
border: none;
font-size: 1.2rem;
font-weight: 100;
&:focus {
outline: #0b5a68 solid 1px;
border: none;
box-shadow: 0 0 4px #0b5a68;
}
}
@media screen and (max-width:768px){
grid-template-columns: 1fr;
align-self: center;
justify-content: center;
}
.block{
display: grid;
grid-template-rows: auto auto;
grid-gap:.25rem;
}
}
.textarea-row{
@media screen and (max-width:768px){
grid-template-columns: auto;
align-self: center;
justify-content: center;
}
.block{
display: grid;
grid-template-rows: auto auto;
grid-gap:.25rem;
@media screen and (max-width:768px){
grid-template-columns: 1fr;
align-self: center;
justify-content: center;
}
textarea{
padding-left: 1rem;
height: 2.5rem;
outline: coral solid 1px;
border: none;
&:focus {
outline: #0b5a68 solid 1px;
box-shadow: 1px 1px 20px #0b5a68;
border: none;
box-shadow: 0 0 4px #0b5a68;
}
height: 4rem;
padding: 1rem 0 0 1rem;
font-size: 1.2rem;
font-weight: 100;
}
}
}
.btn-row{
display: grid;
grid-template-columns: 1fr 1fr 1fr 1fr;
grid-gap:1rem;
@media screen and (max-width:768px){
grid-template-columns: auto;
align-self: center;
justify-content: center;
grid-template-columns: 1fr 1fr;
}
.submit-btn{
display: grid;
justify-content: center;
align-items: center;
width: 100%;
color: white;
background-color: #108397;
border: solid #108397 2px;
border-radius: 4px;
padding: 1rem 1rem;
text-decoration: none;
font-size: 1rem;
font-weight: 600;
outline: none;
&:hover{
background-color: #0b5a68;
border: solid #0b5a68 2px;
transition: ease .3s;
}
}
.cancel-btn{
display: grid;
justify-content: center;
align-items: center;
width: 100%;
color: white;
background-color: #df60b5c7;
border: solid #df60b59c 2px;
border-radius: 4px;
padding: 1rem 1rem;
text-decoration: none;
font-size: 1rem;
font-weight: 600;
outline: none;
&:hover{
background-color: #b4348a;
border: solid #b4348a 2px;
transition: ease .3s;
}
}
}
}
}
我的Quote.jsx文件-
import './Quote.css';
import React, { useState } from 'react';
import axios from 'axios';
<div className="form">
<div className='container'>
<fieldset className='preference'>
<legend>Select your preference</legend>
<div className="preference-row">
<input className="check" checked={radio==="short-term-use"} onChange={e=>setRadio(e.target.value)} type="radio" name="shortTermUse" value="short-term-use" />
<label for="short-term-use">Short Term Use</label>
</div>
<div className="preference-row">
<input className="check" checked={radio==="long-term-use"} onChange={e=>setRadio(e.target.value)} type="radio" name="longTermUse" value="long-term-use" />
<label for="long-term-use">Long Term Use</label>
</div>
</fieldset>
<div className="btn-row">
<button className="submit-btn" onClick={handleSubmit}>Submit</button>
<button className="cancel-btn" onClick={handleCancel}>Cancel</button>
</div>
</div>
</div>
我的Quote.scss文件-
// it's empty
React 默认没有 class 封装,如果你想实现 CSS 风格的封装
,你可以阅读 this article 关于你的选项另见@Jacob Smit 在下面的评论中提到的CSS modules。