专栏首页IMWeb前端团队5件您可能不知道可以使用 CSS-in-JS 来做的事情

5件您可能不知道可以使用 CSS-in-JS 来做的事情

本文作者:IMWeb howenhuo 原文出处:IMWeb社区 未经同意,禁止转载

原文链接:5 things you can do in CSS-in-JS that you didn't know about

除了传统的 CSS,您还可以使用 内联样式CSS-in-JS 作为 React 应用程序的样式选项。

对于内联样式,您可以将 JavaScript对象传递给样式属性:

const myStyle = {
  fontSize: 24,
  lineHeight: '1.3em',
  fontWeight: 'bold',
};

<span style={myStyle}>Hello World!</p>

然而,并非所有 CSS 特性都受支持。

另一方面,CSS-in-JS 是一种使用 JavaScript来设置组件样式的技术。在解析此 JavaScript时,会生成 CSS(通常作为 <style> 元素)并附加到 DOM 中。

这个功能由第三方库实现。例如,下面是使用 Aphrodite 实现的上一个示例:

import { StyleSheet, css } from 'aphrodite';
const styles = StyleSheet.create({
    myStyle: {
        fontSize: 24,
        lineHeight: '1.3em',
        fontWeight: 'bold',
    }
});

<span className={css(styles.myStyle)}>Hello World!</p>

其他第三方库推荐:

我并不完全赞成使用 CSS-in-JS,但我不得不说,其中一些库增加了对在某些情况下可能会有用的功能支持。

在这篇文章中,我将讨论在 CSS-in-JS 中你可以用上面的库来做的五件事,而我打赌这是你不知道的。

1.参照其他样式组件

styled-componentsemotion 库允许您使用 标记模板文字 从样式中创建 React 组件:

import styled from 'styled-components';
// Create a component that renders a <p> element with blue text
const BlueText = styled.p`
  color: blue;
`;

<BlueText>My blue text</BlueText>

它们也允许您定位于其他样式组件(像您使用 CSS 选择器一样):

const ImportantText = styled.div`
   font-weight: bold;
`;

const Text = styled.div`
  color: gray;
  ${ImportantText} {
    font-style: italic;
  }
`;

render(
  <div>
    <Text>
      Text in gray
      <ImportantText>Important text in gray, bold and italic</ImportantText>
    </Text>
    <ImportantText>Important text bold</ImportantText>
  </div>
);

这在组合伪类时很有用,例如,在悬停时更改组件的颜色:

const Text = styled.div`
  color: gray;
  &:hover ${ImportantText} {
    color: red;
  }
`;

2.使用JSS(或其他库)扩展某些库的特性

假设您已经使用 Aphrodite 为您的应用程序设计样式,现在您需要支持主题。

但问题是 Aphrodite 不能轻易地支持主题。 至少不像 Emotion 那么容易。

不过,这里有两个项目将 JSS 的核心与 Aphroditestyled-components 相结合,aphrodite-jssstyled-jss

通过这种方式,您可以保留 Aphrodite(或 styled-components) 的优点,并使用 JSS 的所有特性和 插件,从 规则缓存规则隔离,以及主题,主题包,以下是它提供的高阶组件:

  • ThemeProvider:通过 context 向 react 树传递主题对象。
  • withTheme:允许您接收一个主题对象并作为属性来更新。

例如:

const blackTheme = {
  color: 'black',
};

const App = () => (
  <ThemeProvider theme={blackTheme}>
    <MyComponent />
  </ThemeProvider>
);

Aphrodite 和主题的案例中,作为另一个例子,你也可以使用 react-with-styles,它有实现 AphroditeJSS 接口,这样在定义样式时就可以访问主题信息了。

3.使用关键帧链接多个动画

与内联样式不同,CSS-in-JS 允许您使用关键帧定义动画。 例如,这是使用 styled-components 做的:

const heightAnimation = keyframes`
  0% { height: 0; }
  100% { height: 200; }
`;

const myComponent = styled.div`
  display: inline-block;
  width: 200;
  position: relative;
  animation-name: ${heightAnimation};
  animation-duration: 1.5s;
  animation-timing-function: ease;
`;

但是很多人不知道的是,你可以通过在 animation 属性中使用多个关键帧对象来链接多个动画。 下面是修改后的两个动画的例子:

const heightAnimation = keyframes`
  0% { height: 0; }
  100% { height: 200; }
`;

const rotateAnimation = keyframes`
  0% { transform: rotate(0deg); }
  100% { transform: rotate(360deg); }
`;

const myComponent = styled.div`
  display: inline-block;
  width: 200;
  position: relative;
  animation: ${props => css`
    ${heightAnimation} 1.5s ease infinite,
    ${rotateAnimation} 1.5s linear infinite
  `}
`;

Radium 是另一个通过传递关键帧对象数组作为 animationName 属性值来支持多个 动画 的库:

const heightAnimation = Radium.keyframes(
  {
    0% { height: 0; }
    100% { height: 200; }
  },
  'myHeightAnimation',
);

const rotateAnimation = Radium.keyframes(
  {
    0% { transform: rotate(0deg); }
    100% { transform: rotate(360deg); }
  },
  'myRotateAnimation',
);

const styles = {
  myStyle: {
    animationName: [heightAnimation, rotateAnimation],
    animationDuration: '1.5s, 1s',
    animationIterationCount: 'infinite, infinite',
    animationTimingFunction: 'ease, linear',
    display: inline-block;
    width: 200;
    position: relative;
  },
};

4.声明全局样式

CSS 中的一切都是全局的,使用 CSS-in-JS 的目的之一是消除全局样式定义。

但是,全局样式的使用有时可能是很有效的,例如,当您想对页面中的每个元素应用相同的字体样式时。

当然,您总是可以使用传统的 CSS,通过 Webpack 导入或在 index.html 文件中声明它。

但是,如果您真的想在所有样式中使用 JavaScript,那么有些库实际上允许您通过 helper 组件或扩展/插件来定义全局样式。

Radium 中,您可以使用 Style 组件来渲染具有全局样式的样式元素。 例如:

<Style
  rules={{
    body: {
      fontFamily: 'Arial, Helvetica, sans-serif'
    }
  }}
/>

将返回:

<style>
body {
  font-family: 'Arial, Helvetica, sans-serif';
}
</style>

JSS 使用一个 插件 来编写全局样式:

const styles = {
  '@global': {
    body: {
      fontFamily: 'Arial, Helvetica, sans-serif'
    }
  }
}

Aphrodite 中,你可以用 第三方扩展 来做:

import {injectGlobalStyles} from "aphrodite-globals";

injectGlobalStyles({
    "body": {
          fontFamily: 'Arial, Helvetica, sans-serif',
    }
});

或者通过 aphrodit-jss 来使用 JSS 全局插件。

5.在单元测试中使用样式测试组件

有些库包含用于测试组件样式的工具。

Aphrodite 提供了一个没有文档说明(至少在写这篇文章的时候是这样)的对象StyleSheetTestUtils,它仅适用于非生产环境(process.env.NODE_ENV!=='production'),有三个方法:

  • suppressStyleInjection:它阻止样式被注入到DOM中,当你想要在没有DOM的情况下测试Aphrodite 组件的输出时非常有用。
  • clearBufferAndResumeStyleInjection:它与 suppressStyleInjection 相反,所以它们应该搭配使用。
  • getBufferedStyles:它返回尚未刷新的缓冲样式字符串。

以下是如何使用它们的示例:

import { StyleSheetTestUtils, css } from 'aphrodite';
//...

beforeEach(() => {
  StyleSheetTestUtils.suppressStyleInjection();
});

afterEach(() => {
  StyleSheetTestUtils.clearBufferAndResumeStyleInjection();
});

test('my test', () => {
  const sheet = StyleSheet.create({
    background: {
      backgroundColor: 'blue'
    },
  });
  css(sheet.background);
  // buffer will contain something like [ ".background_k554e1{background-color:blue !important;}" ]
  const buffer = StyleSheetTestUtils.getBufferedStyles();
  // ...
});

Radium 是另一个例子。它有一个 TestMode 对象,用于在测试期间使用 clearStateenabledisable 方法控制内部状态和行为。

这里,您可以找到如何使用它的示例。

结论

CSS-in-JS 是一种使用 JavaScript为应用程序设置样式的技术,您可以使用实现它的库来做有趣的事情。

在这篇文章中,我向您展示了5件您可能不知道可以使用这些库来做的事情。当然,并不是所有的库都是对等的,有些情况只适用于特定的库。

在这个 页面 中,您可以测试和比较许多 CSS-in-JS 的库。

另一方面,还有其他库正在进一步采用 CSS,JavaScript和类型的概念。

其中一个库是 stylable,一个基于组件的库,带有一个预处理器,可以将 stylable 的 CSS 转换成最小的跨浏览器的 vanilla CSS。

这里有一个关于这个库和 CSS-in-JS 的 精彩演示。 非常推荐。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • h5 geolocation 的那些事~

    在讲h5 的geolocation API之前,让我们先了解一下当前国内地理坐标系现状 当前国内地理坐标系 国际坐标系:国际标准,国际地图提供商使用的坐标系 火...

    IMWeb前端团队
  • h5 geolocation 的那些事~

    在讲h5 的geolocation API之前,让我们先了解一下当前国内地理坐标系现状

    IMWeb前端团队
  • react css组织的另一种选择styled-components

    写 React 的同学肯定纠结过 CSS 该怎么组织的问题。传统 WEB 开发里面推崇的 CSS、JS、HTML 关注点分离不建议把 CSS 写到 JS 里面,...

    IMWeb前端团队
  • MySQL存储过程where条件执行失败的问题

          前几天对服务器实体做了属性缓存机制,当时测试也没有出现大的问题,昨天有人跟我说,登陆的时候角色等级显示错误,我复测了一下,发现不只是等级错误,进入...

    帘卷西风
  • Kotlin实战【四】迭代事物:while和for

    区间本质:两个值之间的间隔。这两个值通常是数字:一个是起始值,一个是结束值。使用 ..来表示

    先知先觉
  • 工信部:网络强国建设2018年重点工作任务

    2018年全国工业和信息化工作会议昨日在京开幕,会议提出了我国网络强国建设2018年重点工作任务。 抓住网络信息技术革命的重大机遇,构建技术、设施、安全的强国基...

    企鹅号小编
  • 小白学数据:小世界网络中的大世界

    大数据文摘
  • 云杉网络发布数据驱动的云网可视化与分析产品

    网络与业务正在脱节 通常来说,企业业务的经营与管理离不开“业务架构”、“应用系统”和“IT基础设施”三个有机部分。其中,应用系统是业务的直观体现,而业务架构彰显...

    SDNLAB
  • Windows系统如何安装Tensorflow Object Detection API

    TensorFlow™ 是一个采用数据流图(data flow graphs),用于数值计算的开源软件库。节点(Nodes)在图中表示数学操作,图中的线(edg...

    OpenCV学堂
  • 基于风险的应用程序安全方法可增强安全防御

    如今,不可否认的是网络犯罪已逐渐进入人们的生活,为人们所重视。无论何时,随意浏览新闻都能看到新漏洞的发现,或者是敏感信息的泄露、窃取等。因此,任何企业董事会都应...

    FB客服

扫码关注云+社区

领取腾讯云代金券