likes
comments
collection
share

两种方式轻松做react css样式隔离

作者站长头像
站长
· 阅读数 16

引言

在书写react组件时,如果写了相同的样式类名,很容易造成样式跨组件污染

在vue.js框架中做css样式隔离可以直接在style标签上加scoped 它的原理是通过 Postcss 工具来实现的,Postcss会对vue组件样式做代码转换,达到样式唯一效果

问题

但在react中,官方并没有给我们做样式隔离处理,虽然我们可以借助一些css库来达到样式隔离效果,比如styled-components,但自己如何能实现呢

本文介绍两种方式

  1. 使用 namespaces 空间命名来隔离CSS
  2. 使用 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文件

两种方式轻松做react css样式隔离 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样式,但不会出现覆盖情况

两种方式轻松做react css样式隔离

总结

css样式隔离的方法各有千秋,适合自己的才是最好的! 坚持学习!耀眼一点,你有资格!

往期精彩文章

🌟彻底理解redux的中间件原理 🌟canvas实现刮刮奖效果 🌟前端实现pdf下载 🌟web前端性能优化(全汇总) 🌟一句话概括this指向问题 🌟MutationObserver 实现微任务原理分析 🌟遇到几次的大厂笔试题:装饰数组push方法 🌟V8垃圾回收策略与GC算法 🌟浏览器缓存策略(强缓存和协商缓存) 🌟$nextTick 源码解读与原理分析 🌟手动封装适合react hook使用的状态管理工具

转载自:https://juejin.cn/post/7105563657672589319
评论
请登录