React CSS 终极指南:从行内样式到模块化,打造完美组件样式方案

准备工作

首先创建一个react项目,执行npx create-react-app react-css

然后再创建一个components,文件夹,在本篇中以一个例子会在components下创建一个组件来进行演示。

第一种用法: 行内css

js 复制代码
export default function StyleCssComponent() {
  return (
    <button
      style={{
        outline: "none",
        border: "none",
        borderRadius: "5px",
        backgroundColor: "#409EFF",
        fontSize: "14px",
        color: "#fff",
        padding: "6px 12px",
      }}
    >
      按钮
    </button>
  );
}

行内css 书写注意点:

  1. 要写在一个对象里面
  2. 两个单词的属性需要采用驼峰写法

行内样式的优缺点:

优点: 可以动态计算,所以行内css 的使用场景一般是需要进行动态计算的时候才会用到,比如说动态获取窗口变化来计算当前盒子的宽高

缺点: 行内样式写多了会使代码的结构看上去非常乱,且不好维护,也不好重用

第二种写法: 普通css 文件导入

1. 静态类名写法

ClassCssComponent.css

css 复制代码
.btn-primary {
  outline: none;
  border: none;
  border-radius: 5px;
  background-color: #409EFF;
  font-size: 14px;
  color: #fff;
  padding: 6px 12px;
}

组件里面进行导入使用:

js 复制代码
import "../assets/css/ClassCssComponent.css";
export default function ClassCssComponent() {
  return <button className="btn-primary">按钮</button>;
}

采用css文件导入的写法的注意点: 标签上使用className 进行使用,而不是class

需要根据条件来写class 的写法,比如说button 按钮上默认有一个class 类名,另一个class 类名需要更根据条件进行添加怎么写呢?

2. 第一种动态类名写法

ClassCssComponent.css

css 复制代码
.btn {
  outline: none;
  border: 1px solid #ddd;
  border-radius: 5px;
  font-size: 14px;
  color: #ccc;
  padding: 6px 12px;
}
.btn-primary {
  background-color: #409EFF;
  color: #fff;
}

ClassCssComponent.js

js 复制代码
import "../assets/css/ClassCssComponent.css";
export default function ClassCssComponent() {
  const type = "primary";
  return <button className={"btn " + (type ? "btn-primary" : "")}>按钮</button>;
}

这种写法只有一种情况的判断的的时候看上去没太大问题,但是如果有多种情况,比如说还有btn-success, btn-info,btn-warning, btn-danger,那么这个三元表表达式就会变得很复杂,会使代码阅读变得非常困难。

3. 第二种动态类名写法

ClassCssComponent.css

css 复制代码
.btn {
  outline: none;
  border: 1px solid #ddd;
  border-radius: 5px;
  font-size: 14px;
  color: #333;
  padding: 6px 12px;
  background-color: #fff;
}
.btn-primary {
  background-color: #409EFF;
  color: #fff;
}
.btn-success {
  background-color: #67C23A;
  color: #fff;
}
.btn-info {
  background-color: #909399;
  color: #fff;
}
.btn-warning {
  background-color: #E6A23C;
  color: #fff;
}
.btn-danger {
  background-color: #409EFF;
  color: #F56C6C;
}
js 复制代码
import "../assets/css/ClassCssComponent.css";
export default function ClassCssComponent() {
  const type = "primary";
  let btnTypeClass = "";
  if (type === "primary") {
    btnTypeClass = "btn-primary";
  } else if (type === "success") {
    btnTypeClass = "btn-success";
  } else if (type === "info") {
    btnTypeClass = "btn-info";
  } else if (type === "warning") {
    btnTypeClass = "btn-warning";
  } else if ("danger") {
    btnTypeClass = "btn-danger";
  }
  return <button className={"btn " + btnTypeClass}>按钮</button>;
}

这种情况相对于第一种解决方案,在有多种条件来判断class类名的添加的时候,相对会好一些,但是这也不是太完美的一种写法。再想想有没有一种写法可想以和Vue 那样,写成一个对象,键名是class 类名称,值的真假来决定这个class 类名要不要显示呢?其实是有办法的,可以借助第三方库来实现。

4. 第三种动态类名写法(借助classNames)

安装 classnames

npm i classnames

使用:

js 复制代码
import "../assets/css/ClassCssComponent.css";
import classnames from "classnames";
export default function ClassCssComponent() {
  const type = "primary";
  const btnTypeClass = classnames("btn", {
    "btn-primary": type === "primary",
    "btn-success:": type === "success",
    "btn-info": type === "info",
    "btn-warning": type === "warning",
    "btn-danger": type === "danger",
  });
  return <button className={btnTypeClass}>按钮</button>;
}

这样同样能达到前面的效果,写法比之前好看多了。

classname 也支持数组形式的写法:

js 复制代码
import "../assets/css/ClassCssComponent.css";
import classnames from "classnames";
export default function ClassCssComponent() {
  const type = "primary";
  const btnTypeClass = classnames([
    "btn",
    {
      "btn-primary": type === "primary",
      "btn-success:": type === "success",
      "btn-info": type === "info",
      "btn-warning": type === "warning",
      "btn-danger": type === "danger",
    },
  ]);
  return <button className={btnTypeClass}>按钮</button>;
}

classnames还支持很多种写法,更多写法可以查看官方文档 github.com/JedWatson/c...

三、模块化css

到这里class 的写法已接近完美了,但其实还是存在一些问题,组件之间的样式会相互影响。

来看个案例,现在有两个组件,一个BoxComponent1.js,一个BoxComponent2.js,BoxComponent1.js导入一个BoxComponent1.css, 一个BoxComponent2.js导入BoxComponent2.css

BoxComponent1.js

js 复制代码
import "../assets/css/BoxComponent1.css";
export default function BoxComponent1() {
  return <div className="box">box1</div>;
}

BoxComponent1.css

css 复制代码
.box {
  width: 100px;
  height: 100px;
  background: #f00;
  color: #fff;
  font-size: 40px;
  margin: 20px;
  display: flex;
  justify-content: center;
  align-items: center;
}

BoxComponent2.js

js 复制代码
import "../assets/css/BoxComponent2.css";
export default function BoxComponent2() {
  return <div className="box">box2</div>;
}

BoxComponent2.css

css 复制代码
.box {
  width: 200px;
  height: 200px;
  background: greenyellow;
  color: #fff;
  font-size: 40px;
  margin: 20px;
  display: flex;
  justify-content: center;
  align-items: center;
}

按照我们的想法这两个样式应该是不一样的,box1是红色,box2是绿色,box1宽高是100px,box2宽高是200px。但是当你打开浏览器的时候你会惊奇的发现,两个样式显示居然是一样的,都采用了box2的样式。如下图:

这显然不是我们想要的效果。为什么会出现这种情况呢,因为 create-react-app 创建的项目是单页面应用,虽然我们把css 写在了不同的文件,但是打包之后css都会打包到一个文件里面。来执行下打包命令 npm run build 看下是不是这样的.

可以看到box1和box2的都合并到了一个里面。这就是造成样式互相影响的原因,在开发环境是直接将css 全部都放入到了页面的style中。

这样同样都会相互影响。那这个问题怎么解决呢?这个时候就需要用到css模块化了。npx create-react-app 创建的项目 已经自带css 模块化了,不需要再去安装依赖。来看下具体的使用。

  1. 首先需要将BoxComponent1.css改成 BoxComponent1.module.css
  2. 修改BoxComponent1.js中修改导入路径为: import box1Css from "../assets/css/BoxComponent1.module.css";
  3. 使用类名由 className="box"改为className={box1Css.box}

修改后的BoxComponent1.js如下

js 复制代码
import box2Css from "../assets/css/BoxComponent2.module.css";
export default function BoxComponent2() {
  return <div className={box2Css.box}>box2</div>;
}

BoxComponent2 的修改方式和BoxComponent1一样。

修改完成之后,查看效果:

可以看到,现在就使用了各自的样式了。css 模块化这怎么做到样式隔离的呢,css模块会在编译后会给我们的类名加一个前缀和后缀,前缀为组件名称,后缀是随机字符串。

这样我们就很好的解决了样式隔离问题。

今天就分享到这里了,感谢收看,本篇收录到React 知识储备专栏,欢迎关注后续更新

相关推荐
Arvin6271 小时前
Nginx IP授权页面实现步骤
服务器·前端·nginx
初遇你时动了情1 小时前
react/vue vite ts项目中,自动引入路由文件、 import.meta.glob动态引入路由 无需手动引入
javascript·vue.js·react.js
摇滚侠2 小时前
JavaScript 浮点数计算精度错误示例
开发语言·javascript·ecmascript
xw52 小时前
Trae安装指定版本的插件
前端·trae
天蓝色的鱼鱼2 小时前
JavaScript垃圾回收:你不知道的内存管理秘密
javascript·面试
默默地离开2 小时前
前端开发中的 Mock 实践与接口联调技巧
前端·后端·设计模式
南岸月明2 小时前
做副业,稳住心态,不靠鸡汤!我的实操经验之路
前端
嘗_2 小时前
暑期前端训练day7——有关vue-diff算法的思考
前端·vue.js·算法
伍哥的传说3 小时前
React 英语打地鼠游戏——一个寓教于乐的英语学习游戏
学习·react.js·游戏
MediaTea3 小时前
Python 库手册:html.parser HTML 解析模块
开发语言·前端·python·html