为在PayPal的产品构建一些东西

61 阅读3分钟

我正在为我在PayPal的产品构建一些东西(博客文章可能即将发布),并且厌倦了写这样的组件:

const styles = glamor.css({
  fontSize: 20,
  textAlign: 'center',
})
function MyStyledDiv({className = '', ...rest}) {
  return <div className={`${styles} ${className}`} {...rest} />
}

所以我决定尝试一下styled-components,因为它的宣传力度很大🚂。我真的很喜欢它:

twitter.com/kentcdodds/…

它让我可以把同一个组件写成这样:

const MyStyledDiv = styled.div`
  font-size: 20px;
  text-align: center;
`

制作可组合的组件,并将其样式带在身上,这实在是太了不起了。

不幸的是,当我意识到目前还没有一个从右到左转换的解决方案(如CSSJanusrtl-css-js)时,我碰了壁,而这对我正在构建的东西来说是一个硬性要求。我当时对样式化组件的尺寸也有一些问题(注意,如果你愿意放弃一些动态功能,你可以转译掉很多尺寸,我不愿意这么做)。

因此,在评估了一堆其他的解决方案,并试图增强现有的解决方案,使其成为我想要的样子之后,我决定创建我自己的解决方案。

进入glamorous 💄!

paypal/glamorous

glamorous 是React组件造型的解决方案,具有优雅(灵感)的API,占地面积小( gzipped),性能好(通过<5kb glamor).它有一个与styled-components非常相似的API,并在引擎盖下使用类似的工具(glamor)。其好处是。

twitter.com/kentcdodds/…

让我们快速了解一下迷人的组件是什么样子的:

// Create a <Title> react component that renders an <h1> which is
// centered, palevioletred and sized at 1.5em
const Title = glamorous.h1({
  fontSize: '1.5em',
  textAlign: 'center',
  color: 'palevioletred',
})

// Create a <Wrapper> react component that renders a <section> with
// some padding and a papayawhip background
const Wrapper = glamorous.section({
  padding: '4em',
  background: 'papayawhip',
})

function App() {
  return (
    <Wrapper>
      <Title>Hello World, this is my first glamorous component!</Title>
    </Wrapper>
  )
}

(感谢styled-components提供的例子灵感)。

glamorous的魅力在于,所有你能用glamor做的酷事,你都能用glamorous做。 下面是几个例子。

伪眼镜

const MyLink = glamorous.a({
  ':hover': {
    color: 'red',
  },
})

子选择器 (你应该很少使用的逃生舱门,但有它就好了)

const MyDiv = glamorous.div({
  display: 'block',
  '& .bold': {fontWeight: 'bold'},
  '& .one': {color: 'blue'},
  ':hover .two': {color: 'red'},
})

const ui = (
  <MyDiv>
    <div className="one bold">is blue-bold!</div>
    <div className="two">hover red!</div>
  </MyDiv>
)

媒体查询

const MyResponsiveDiv = glamorous.div({
  width: '100%',
  padding: 20,
  '[@media](http://twitter.com/media "Twitter profile for @media")(min-width: 400px)':
    {
      width: '85%',
      padding: 0,
    },
})

动画

import {css} from 'glamor' // or require or whatever...

const bounce = css.keyframes({
  '0%': {transform: 'scale(1)', opacity: 0.3},
  '55%': {transform: 'scale(1.2)', opacity: 1},
  '100%': {transform: 'scale(1)', opacity: 0.3},
})

const MyBouncyDiv = glamorous.div({
  animation: `${bounce} 1s infinite`,
  width: 50,
  height: 50,
  backgroundColor: 'red',
})

主题化

通过新的ThemeProvider (最近由Alessandro Arnodo添加),glamorous也支持主题化。

const Title = glamorous.h1(
  {
    fontSize: '10px',
  },
  (props, theme) => ({
    color: theme.main.color,
  }),
)

// use <ThemeProvider> to pass theme down the tree
const ui1 = (
  <ThemeProvider theme={theme}>
    <Title>Hello!</Title>
  </ThemeProvider>
)

// it is possible to nest themes
// inner themes will be merged with outers
const ui2 = (
  <ThemeProvider theme={theme}>
    <div>
      <Title>Hello!</Title>
      <ThemeProvider theme={secondaryTheme}>
        {/\* this will be blue */}
        <Title>Hello from here!</Title>
      </ThemeProvider>
    </div>
  </ThemeProvider>
)

如果你需要全局样式,你可以直接用glamor来做(你也可以用styled-components做这个)。还有很多其他很酷的事情你可以用glamor来做(包括服务器端渲染)!

glamorous 的另一个伟大功能是它会为你自动合并glamor的类名。在这里了解更多信息。


除了受风格化组件启发的API之外,glamorous 还暴露了一个受jsxstyle启发的API。有时候,你不想给某个东西起名字,因为给东西起名字很困难。特别是对于这种东西,你会发现有很多名字,比如ContainerWrapper ,谁知道哪个是哪个!?所以,如果你发现某样东西并不真正需要一个名字,那么就不要给它起名字!(有趣的提示:这也适用于所有的人。

const {Div, A} = glamorous

function App() {
  return (
    <Div textAlign="center" color="red">
      <A
        href="[https://brave.com/](https://brave.com)"
        textDecoration="none"
        color="darkorange"
        textShadow="1px 1px 2px orange"
      >
        Browse faster and safer with Brave.
      </A>
      <div>It's fast, fun, and safe!</div>
    </Div>
  )
}

(有趣的提示:这也适用:<glamorous.Div>JSX!!</glamorous.Div>)

哦,只是为了好玩,所有这些围绕着CSS Grid的兴奋让你垂涎三尺? 它被glamorous微不足道地支持。

// Example inspired by
// [http://gridbyexample.com/examples/example12/](http://gridbyexample.com/examples/example12)
const MyGrid = glamorous.div({
  margin: 'auto',
  backgroundColor: '#fff',
  color: '#444',
  // You can use [@supports](http://twitter.com/supports "Twitter profile for @supports") with glamor!
  // So you can use [@supports](http://twitter.com/supports "Twitter profile for @supports") with glamorous as well!
  '[@supports](http://twitter.com/supports "Twitter profile for @supports") (display: grid)':
    {
      display: 'grid',
      gridGap: 10,
      gridTemplateAreas: `  
      "....... header header"  
      "sidebar content content"  
      "footer  footer  footer"  
    `,
    },
})

const Box = glamorous.div({
  backgroundColor: '#444',
  color: '#fff',
  borderRadius: 5,
  padding: 10,
  fontSize: '150%',
})

const HeaderFooter = glamorous(Box)({
  backgroundColor: '#999',
})

function App() {
  return (
    <MyGrid>
      <HeaderFooter css={{gridArea: 'header'}}>Header</HeaderFooter>
      <Box css={{gridArea: 'sidebar'}}>Sidebar</Box>
      <Box css={{gridArea: 'content'}}>
        Content
        <br />
        More content than we had before so this column is now quite tall.
      </Box>
      <HeaderFooter css={{gridArea: 'footer'}}>Footer</HeaderFooter>
    </MyGrid>
  )
}

你会得到