美文网首页Python,web开发,前端技术分享让前端飞
5件你可能不知道可以使用 CSS-in-JS 来做的事情

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

作者: 一墨编程学习 | 来源:发表于2018-12-27 23:10 被阅读2次

    除了传统的 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。

    相关文章

      网友评论

        本文标题:5件你可能不知道可以使用 CSS-in-JS 来做的事情

        本文链接:https://www.haomeiwen.com/subject/rgrjlqtx.html