Skip to content

CSS 解决方案

由于 CSS 都是全局的,因此在大项目中容易出现样式污染的问题。

可以通用用程序生成全局不冲突(即唯一的)的选择器来解决样式污染的问题。

React 栈推荐使用 CSS Modules 和 CSS in JS

classnames

classnames 是一个动态设置样式类的库,比如不同用户组使用不同样式。 首先来安装库

text
npm i classnames

在一些复杂的场景中,一个元素可能对应多个 className,而每个 className 又基于一些条件来决定是否出现。 这时,classnames 这个库就非常有用。

jsx
import classnames from 'classnames';

function App(props) {
  const cls = classnames({
    btn: true,
    btnLarge: props.type === 'submit',
    btnSmall: props.type === 'edit',
  });
  return (
    <div className={cls} />
  );
}

这样,传入不同的 type 给 App 组件,就会返回不同的 className 组合:

text

<App type="submit" /> // btn btnLarge
<App type="edit" />   // btn btnSmall
ts
function mergeClass(...source: any[]) {
  const classes: string[] = [];
  source.filter(Boolean).forEach((s) => {
    if (!s) {
      return;
    }
    if (typeof s === 'string') {
      classes.push(s);
      return;
    }
    if (Array.isArray(s)) {
      classes.push(mergeClass(...s));
      return;
    }
    if (typeof s === 'object') {
      Object.entries(s).forEach(([key, value]) => {
        if (!key || !value) {
          return;
        }
        classes.push(String(key));
      });
    }
  });
  return classes.join(' ');
}

export default mergeClass;
export const classnames = mergeClass;

styled-components

使用社区提供的第三方库来控制样式,下面是使用 styled-components 组件来控制样式

安装扩展包

text
npm i styled-components

CSS Modules

一般来说用上了css module之后,涉及到一些第三方组件,想要改里面的类样式,常常需要:global

比如 要改.third-party-class类的样式,假设父级业务类为customClass,则编码如下:

less
.customClass {
  :global {
    .third-party-class {
      // 这里改第三方类的样式
      font-size: 28px;
    }
  }
}

但如果你的customClass碰巧是和third-party-class同级,比如:(虽然少见,但偶尔也会有)

html
<div class="customClass third-party-class"></div>

这个时候:global的写法就要这么写了

less
.customClass {
  &:global(.third-party-class) {
    // 这里改第三方类的样式
    font-size: 28px;
  }
}

也可以是:(省了三个字符)

less
.customClass:global(.third-party-class) {
  // 这里改第三方类的样式
  font-size: 28px;
}

React 中五种常见的样式策略

https://juejin.cn/post/7041745627323056142 React中的样式策略主要有以下几种:

内联样式: 内联样式就是在JSX元素中,直接定义行内的样式; CSS样式表: 这也是我们最常用的样式策略,使用单独的样式表,使用CSS或者SCSS等来为元素设置样式; CSS模块: CSS模块是一个文件,默认情况下所有类名和动画名都在本地范围; styled-components:这是一个用于React和React Native的样式组件库,它允许我们早应用中使用组件级样式,这些样式就是使用CSS-in-JS的技术来编写的; JSS:JSS是一个CSS创作工具,它允许我们使用JavaScript以声明式、无冲突和可重复的方式来描述样式。

内联样式

React中的组件是由JSX元素组件的,虽然编写的不是常规的HTML,但是仍然是可以使用内联样式去定义样式的。

与普通的HTML内联样式唯一的区别就是,JSX中的内联样式是一个对象,而不是一个字符串。 由于style属性是一个对象,所以我们也可以将这个对象定义成一个常量来分隔样式,这样就可以根据需要在其他组件上重用它:

tsx
import React from 'react';

const h1Style = {
  color: 'red',
  textAlign: 'center'
};

export default function App() {
  return (
    <h1 style={h1Style}>Hello World</h1>
  );
}

如果想要在重用时继续扩展这个样式对象,就可以使用ES6中的扩展运算符来实现:

tsx
import React from 'react';

const h1Style = {
  color: 'red',
  textAlign: 'center'
};

export default function App() {
  return (
    <h1 style={{ ...h1Style, fontSize: '25px' }}>Hello World</h1>
  );
}

除此之外,我们还可以在样式对象中使用变量,这样就能实现样式的动态变化:

tsx
import React from 'react';

export default function App({ themeColor }) {
  const h1Style = {
    color: themeColor,
    textAlign: 'center'
  };

  return (
    <h1 style={h1Style}>Hello World</h1>
  );
}

这也是内联样式最重要的特性之一。但是,React团队并不推荐使用内联样式。内联样式也是CSS-in-JS技术的最基本的示例。

内联样式的优点:

使用简单: 使用内联样式的好处就是简单的以组件为中心来实现样式的添加; 扩展方便: 通过使用对象进行样式设置,可以方便的扩展对象来扩展样式; 避免冲突: 样式通过对象的形式定义在组件中,避免了和其他样式的冲突。

在大型项目中,内联样式可能并不是一个很好的选择,因为内联样式还是有局限性的:

不能使用伪类: 这意味着 :hover、:focus、:actived、:visited等都将无法使用;

不能使用媒体查询: 媒体查询相关的属性不能使用。

减低代码可读性: 如果使用很多的样式,代码的可读性将大大降低。

没有代码提示:当使用对象来定义样式时,是没有代码提示的,所以如果拼错样式属性,也很难检查出来。

Contributors

作者:Long Mo
字数统计:1.3k 字
阅读时长:4 分钟
Long Mo
文章作者:Long Mo
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Longmo Docs