CSS-in-JS 來做的 5 件事情,一般人都不知道!

智雲程式設計發表於2019-01-19

除了傳統的 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-components     emotion   庫允許您使用   標記模板文字   從樣式中建立 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>
);
CSS-in-JS 來做的 5 件事情,一般人都不知道!

這在組合偽類時很有用,例如,在懸停時更改元件的顏色:

const Text = styled.div`
  color: gray;
  &:hover ${ImportantText} {
    color: red;
  }
`;
CSS-in-JS 來做的 5 件事情,一般人都不知道!

2.使用JSS(或其他庫)擴充套件某些庫的特性

假設你已經使用   Aphrodite   為你的應用程式設計樣式,現在你需要支援主題。

但問題是   Aphrodite   不能輕易地支援主題。 至少不像   Emotion   那麼容易。

不過,這裡有兩個專案將   JSS   的核心與   Aphrodite     styled-components   相結合, aphrodite-jss     styled-jss

通過這種方式,你可以保留   Aphrodite (或   styled-components ) 的優點,並使用   JSS   的所有特性和   外掛 ,從   規則快取     規則隔離 ,以及 主題 ,主題包,以下是它提供的高階元件:

  • ThemeProvider :通過 context 向 react 樹傳遞主題物件。
  • withTheme :允許你接收一個主題物件並作為屬性來更新。

例如:

const blackTheme = {
  color: 'black',
};
const App = () => (
  <ThemeProvider theme={blackTheme}>
    <MyComponent />
  </ThemeProvider>
);

  Aphrodite   和主題的案例中,作為另一個例子,你也可以使用   react-with-styles ,它有實現   Aphrodite     JSS   介面,這樣在定義樣式時就可以訪問主題資訊了。

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   物件,用於在測試期間使用   clearState enable     disable   方法控制內部狀態和行為。

  這裡 ,您可以找到如何使用它的示例。

結論

CSS-in-JS 是一種使用 JavaScript為應用程式設定樣式的技術,你可以使用實現它的庫來做有趣的事情。

在這篇文章中,我向你展示了5件你可能不知道可以使用這些庫來做的事情。當然,並不是所有的庫都是對等的,有些情況只適用於特定的庫。

在這個   頁面   中,您可以測試和比較許多 CSS-in-JS 的庫。

另一方面,還有其他庫正在進一步採用 CSS,JavaScript和型別的概念。

其中一個庫是   stylable ,一個基於元件的庫,帶有一個前處理器,可以將 stylable 的 CSS 轉換成最小的跨瀏覽器的 vanilla CSS。


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69901074/viewspace-2564208/,如需轉載,請註明出處,否則將追究法律責任。

相關文章