簡體   English   中英

Emotion CSS-in-JS - 如何基於組件道具添加條件 CSS?

[英]Emotion CSS-in-JS - how to add conditional CSS based on component props?

我想要一個帶有Emotion樣式的組件,它采用最終控制樣式的道具。 例如,考慮一個GridCol組件,它有各種改變內邊距和寬度的道具(寬度可以在不同的視口寬度之間改變)。

我想使用這樣的 API:

<GridCol gutter size="2>

// or alternatively, like this:

<GridCol gutter size={{
  m: 2,
  l: 4
}}>

這里發生了三件事:

  • gutter是一個布爾道具,它向列添加一些水平填充
  • size道具可以是字符串或對象。 如果它是一個字符串,我們只需添加幾行 CSS 就可以了,但是,如果它是一個對象,我們需要根據在別處設置的斷點對象插入一些媒體查詢。

Emotion 的文檔不清楚如何處理這種性質的樣式,至少我沒有見過,所以我希望能找到一個通用的解決方案。

對於gutter道具,它是微不足道的:

const GridCol = props => styled('div')`
  display: block;
  box-sizing: border-box;
  flex: 1 0 0;
  min-width: 0;
  padding: ${props.gutter ? `0 10px` : '0'};
`

對於size道具,它變得更加復雜,我希望生成的 CSS 看起來像這樣:

const GridCol = props => styled('div')`
  display: block;
  box-sizing: border-box;
  flex: 1 0 0;
  min-width: 0;
  padding: ${props.gutter ? `0 10px` : '0'};

  /* styles here if  `size` is a string */
  width: 10%;

  /* styles here if  `size` is an object */
  @media screen and (min-width: 500px) {
      width: 20%;
  }


  @media screen and (min-width: 800px) {
      width: 30%;
  }


  @media screen and (min-width: 1100px) {
      width: 40%;
  }
`

width值將由 prop 的 key 決定,它對應於breakpoints對象中的一個值,這部分不是微不足道的,但我不知道如何動態生成所需的 css。

我確定我可以添加更多信息,我進行了一些嘗試,但目前都沒有工作。 我的感覺是我應該創建一個無狀態的功能組件,為每個條件生成 css,然后在最后加入 CSS..

這是一個很好的問題。 首先,避免這種模式。

const GridCol = props => styled('div')`
  display: block;
  box-sizing: border-box;
  flex: 1 0 0;
  min-width: 0;
  padding: ${props.gutter ? `0 10px` : '0'};
`

在這個例子中,在每次渲染時都會創建一個新的樣式組件,這對性能來說很糟糕。

任何表達式或插值都可以是函數。 此函數將接收 2 個參數: propscontext

const GridCol = styled('div')`
  display: block;
  box-sizing: border-box;
  flex: 1 0 0;
  min-width: 0;
  padding: ${props => props.gutter ? `0 10px` : '0'};
`

至於您示例中的size道具,我將使用以下模式。

import { css } from 'emotion'

const sizePartial = (props) => typeof props.size === 'string' ?
  css`width: 10%;` :
  css`
   @media screen and (min-width: 500px) {
      width: 20%;
   }


   @media screen and (min-width: 800px) {
      width: 30%;
   }


   @media screen and (min-width: 1100px) {
      width: 40%;
   }
 `

然后,您可以像在表達式中出現的任何其他函數一樣使用部分。

const GridCol = styled('div')`
  display: block;
  box-sizing: border-box;
  flex: 1 0 0;
  min-width: 0;
  padding: ${props => props.gutter ? `0 10px` : '0'};
  ${sizePartial};
`

這是一個非常強大的模式,可用於在您的項目中組合可重用的動態樣式。

如果您對利用此模式的其他庫感興趣,請查看https://github.com/emotion-js/facepainthttps://github.com/jxnblk/styled-system

如果您正在尋找一種使用 Emotion 的css道具實現條件樣式的方法,您可以執行以下操作:

import { css } from '@emotion/core';

const styles = ({ isSelected }) => css`
  border: solid 1px black;
  border-radius: 10px;
  padding: 16px;
  cursor: pointer;
  ${isSelected === true &&
  `
    background-color: #413F42;
    color: white;
  `}
`;

const ConditionalComponent = () => {
  const [isSelected, setIsSelected] = useState(false);
  return (
    <div css={styles({ isSelected })} onClick={() => setIsSelected(!isSelected)}>
      Click here to change styles.
    </div>
  );
};

此處有更多詳細信息: https : //seanconnolly.dev/emotion-conditionals

Emotion 有一個名為cx的幫助程序,它提供類似於流行的類名庫的功能。 您可以使用它來更輕松地編寫條件:

import { cx, css } from '@emotion/css'

const cls1 = css`
  font-size: 20px;
  background: green;
`

const foo = true
const bar = false

const SomeComponentWithProp = ({ foo }) => (
  <div
    className={cx(
      { [cls1]: foo === 'bar' },
    )}
  />
);

(改編自鏈接的文檔)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM