一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第13天,点击查看活动详情。
先写个注意点,我最近一直容易搞忘记的
在scss中使用图片的绝对路径的时候需要加上~
background-image: url(~assets/login.png);
下面我们来演示一下css样式污染的问题
1、首先我们在APP组件里写结构,并且导入APP.SCSS,导入Login组件
import './App.scss';
import Login from './Login'
function App() {
return (
<div className="App">
<div className="box">
APP
</div>
<Login></Login>
</div>
);
}
export default App;
2、在Login页面里写结构
import React from 'react'
const Func = () => {
return <div className="box">
Login
</div>
};
export default Func
3、在APP.SCSS文件里写样式
.box {
height: 200px;
width: 200px;
background-color: yellow;
}
代码运行结果
我们发现Login里的box盒子也生效了样式,但在Login组件里并没有导入APP.SCSS文件,这是为什么呢?
因为React会把每一个样式文件放在head里面,在配置路由时,APP和Login组件都被导入到项目中,那么组件的样式也就被导入到项目中了,也就是说最终的所有的样式文件全汇集到index.html中了。
如果多个组件的样式中出现选择器重复,那么一个组件中的样式就会在另一个组件中也生效,从而造成组件之间样式相互覆盖的问题。
解决方法 在react中推荐使用:CSS Modules (推荐原因:React脚手架已集成,可直接使用)。在vue中默认使用的是scoped css。
1、改样式文件名。从 xx.scss -> xx.module.scss (这是React脚手架中的约定,与普通 CSS 作区分)
2、组件中导入该样式文件(注意语法)
import styles from './index.module.scss'
3、通过 styles 对象访问对象中的样式名来设置样式
import styles from './App.module.scss';
import Login from './Login'
function App() {
return (
<div className="App">
<div className={styles.box}>
APP
</div>
<Login></Login>
</div>
);
}
export default App;
这样样式污染问题就被解决了!
实现的原理是CSS Modules 通过自动给 CSS 类名补足类名,保证类名的唯一性,从而避免样式冲突的问题 。
这个时候看类名已经默认被CSS Modules 补足,保证了类名的唯一性
掌握CssModules-维持类名
在没有做任何处理的情况下, 每一个类名都会被修改。
如果希望某个类名不被修改,可以使用: global。如下:
发现加了: global的类名会维持原状, 不会被修改
维持类名的应用场景
当我们想覆盖第三方组件的样式时,就需要给第三方组件的类名加上global
:global(.ant-btn) {
color: red !important;
}
日常开发时的最佳实践
在对应的index.module.scss
// index.module.scss
.root {
display: 'block';
position: 'absolute';
// 此处,使用 global 包裹其他子节点的类名。此时,这些类名就不会被处理,在 JSX 中使用时,就可以用字符串形式的类名
// 如果不加 :global ,所有类名就必须添加 styles.title 才可以
:global {
.title {
.text {
}
span {
}
}
.login-form { ... }
}
}
在组件中使用就很方便
import styles from './index.module.scss'
const 组件 = () => {
return (
{/* (1) 根节点使用 CSSModules 形式的类名( 根元素的类名: `root` )*/}
<div className={styles.root}>
{/* (2) 所有子节点,都使用普通的 CSS 类名*/ }
<h1 className="title">
<span className="text">登录</span>
<span>登录</span>
</h1>
<form className="login-form"></form>
</div>
)
}