两种方式轻松做react css样式隔离
引言
在书写react组件时,如果写了相同的样式类名,很容易造成样式跨组件污染
在vue.js框架中做css样式隔离可以直接在style标签上加scoped 它的原理是通过 Postcss 工具来实现的,Postcss会对vue组件样式做代码转换,达到样式唯一效果
问题
但在react中,官方并没有给我们做样式隔离处理,虽然我们可以借助一些css库来达到样式隔离效果,比如styled-components,但自己如何能实现呢
本文介绍两种方式
- 使用 namespaces 空间命名来隔离CSS
- 使用 css module 来隔离CSS
namespaces 空间命名
基本: 最基本的写法就是直接统一在类名前加上固定前缀(前缀可以是各自组件名称)
// title即为该组件的唯一前缀
function Title() {
return (
<div className='title'>
<div className='title-name'></div>
<div className='title-time'></div>
<div className='title-content'>
<div className='title-content-item'></div>
<div className='title-content-item'></div>
<div className='title-content-item'></div>
</div>
</div>
)
}
/**
* 相应的样式可以使用 & 符代替前缀(scss)
*/
.title{
&-name{
}
&-time{
}
&-content{
&-item{
}
}
}
提取前缀写法(进阶): 使用工具函数提取(前缀可以是组件名称)
import style from './title.less';
import extractPrefix from 'common/utils/extractPrefix'
// ex函数会给样式类名自动加上前缀
const ex = extractPrefix(style)
function Title() {
return (
<div className={ex('title')}>
<div className={ex('name')}></div>
<div className={ex('time')}></div>
<div className={ex('content')}>
<div className={ex('content-item')}></div>
<div className={ex('content-item')}></div>
<div className={ex('content-item')}></div>
</div>
</div>
)
}
/**
* 相应的less
* 自定义样式前缀prefix
*/
@prefix: title; // 前缀(该组件名,每个组件可以使用自己的名称)
:export {
prefix: @prefix;
}
.@{prefix}{
&-name{
}
&-time{
}
&-content{
&-item{
}
}
}
工具函数extractPrefix:
import classnames from 'classnames';
export default (styles, _prefix) => {
const prefix = _prefix || styles.prefix; // 获取自定义前缀
const cx = classnames.bind(styles); // classnames为一个拼接类名的简单js库
if (!prefix) return cx; //无需函数拼接
// 前缀处理
const handlePrefix = name => {
if (name.startsWith(':')) return name.replace(':', '');
return `${prefix}-${name}`
};
// 遍历传入的类名,使用cx生成类名
// cx参数可以传入字符串、对象等格式,本文只使用字符串案例,详细可上npm查看classnames库
return (...names) =>
cx(
names.map(name => {
if (name === null || name === '' || name === undefined) return ''
// 接受字符串
if (typeof name === 'string') {
return handlePrefix(name)
}
// 接受对象
if (typeof name === 'object') {
const returnObj = {};
Object.keys(name).forEach(key => {
const element = name[key];
returnObj[handlePrefix(element)] = element
})
return returnObj;
}
return ''
})
);
};
CSS Modules
CSS Modules 是什么? 根据CSS Modules项目在github上的翻译: CSS 模块是一个CSS 文件,默认情况下,所有类名和动画名都在本地范围内
意思就是说css modules它不是将 CSS 改造成编程语言,而是功能很单纯,只加入了局部作用域和模块依赖,这恰恰是网页组件最急需的功能,因此,CSS Modules 很容易学,因为它的规则少,同时又非常有用,可以保证某个组件的样式,不会影响到其他组件
CSS Modules在react中的用法: 此处以sass为例 第一步将scss文件中间加入.module,代表为CSS Modules文件
page1的样式为:.title{ color: red; }
page2的样式为:.title{ color: blue; }
第二步引入module文件,以对象的形式使用
import style from './style.module.scss'
function Page1() {
return (
<div>
<div className={style.title}>攀枝花大芒果,便宜好吃包邮</div>
</div>
);
}
export default Page1;
page2同page1一样 最终展示效果:同为.title样式,但不会出现覆盖情况
总结
css样式隔离的方法各有千秋,适合自己的才是最好的! 坚持学习!耀眼一点,你有资格!
往期精彩文章
🌟彻底理解redux的中间件原理 🌟canvas实现刮刮奖效果 🌟前端实现pdf下载 🌟web前端性能优化(全汇总) 🌟一句话概括this指向问题 🌟MutationObserver 实现微任务原理分析 🌟遇到几次的大厂笔试题:装饰数组push方法 🌟V8垃圾回收策略与GC算法 🌟浏览器缓存策略(强缓存和协商缓存) 🌟$nextTick 源码解读与原理分析 🌟手动封装适合react hook使用的状态管理工具
转载自:https://juejin.cn/post/7105563657672589319