glamorous
的简要介绍为什么会有glaomrous这个项目
你喜欢CSS in JS的概念,但是你不喜欢只是为了给组件加样式就给每个组件都写一个包装的函数。你也不喜欢给一个没有任何逻辑的简单组件起个名字。而且,创建样式(这里指代表样式的类名),className
的传递。属性的转发等等的琐碎之事也很让人头疼。
比如说,下面就是你用纯glamor
(或者aphrodite
或者有类似功能的库)需要写的代码:
const styles = glamor.css({
fontSize: 20,
textAlign: 'center',
})
function MyStyledDiv({className = '', ...rest}) {
return (
<div
className={`${styles} ${className}`}
{...rest}
/>
)
}
通过使用glamorous
,上面的例子就可以写成下面这样简单的形式:
const MyStyledDiv = glamorous.div({
fontSize: 20,
textAlign: 'center',
})
实际上,这种方案更好,因为很多用来组合这些组件的特性都棒极了!
恩...如果你觉得给不给MyStyledDiv
起名字并不重要,用个div标签给点样式就行了。那么可以直接这么做:
const { Div } = glamorous
function App() {
return (
<Div
fontSize={20}
textAlign="center"
>
Hello world!
</Div>
)
}
点击这里在你的浏览器中尝试一下。
所以,这就是这种解决方案的基本部分了!接下来让我们了解更多的细节吧!
npm install --save glamorous
glamorous
依赖react
和glamor
,所以如果之前没有安装这些模块的话,你还得在你的项目里面安装他们。
npm install --save react glamor
备注:如果你使用的React版本在15.5或者更高,你还需要安装
prop-types
:npm install --save prop-types
你可以使用下面任何一种模块格式
main
: dist/glamorous.cjs.js
- 通过CommonJS模块的形式导出global
: dist/glamorous.umd.js
and dist/glamorous.umd.min.js
- 通过umd模块的形式导出,可以在几种环境中使用,最常见的是作为全局变量使用jsnext:main
and module: dist/glamorous.es.js
- exports itself using the ES modules specification, you'll need to configure webpack to make use of this file do this using the resolve.mainFields property.jsnext:main
and module: dist/glamorous.es.js
- 通过ES模块规范导出,如果要通过这种形式使用的话你需要在webpack中配置resolve.mainFields属性 不过最常见的场景还是通过CommonJS使用此模块:
const glamorous = require('glamorous')
const {ThemeProvider} = glamorous
如果你在使用转换工具(同时/或者使用jsnext:main)
import glamorous, {ThemeProvider} from 'glamorous'
// 你还可以导入特定的Glamorous组件(详见"内置"组件部分)
import {Div, H2} from 'glamorous'
// 和JavaScript内置对象名字相同的标签可以通过Tag后缀导入
// 包含短横线-的标签会被转换成驼峰风格
import {MapTag, ColorProfile} from 'glamorous'
如果你想以全局变量的形式使用:
<!-- 加载资源 -->
<script src="https://unpkg.com/react/dist/react.js"></script>
<script src="https://unpkg.com/prop-types/prop-types.js"></script>
<script src="https://unpkg.com/glamor/umd/index.js"></script>
<!-- 加载glamorous-->
<script src="https://unpkg.com/glamorous/dist/glamorous.umd.js"></script>
<script>
// 在这里使用window.glamorous
const glamorous = window.glamorous
const {ThemeProvider} = glamorous
</script>
开始使用glamorous
glamorous
函数是默认的导出。它可以创建一个glamorous组件,该组件可以把样式渲染到你所给的React组件。这是通过把一个className
属性转发给你传入的React组件完成的。
在我们学习如何包装自定义组件之前,我们先来聊一聊内置的DOM元素。
对于每一个DOM元素,都有一个对应的glamorous
组件工厂绑定在glamorous
函数上。如上所述,你可以通过诸如:glamorous.div
,glamorous.a
,glamorous.article
之类的形式调用这些工厂函数。
const MyStyledSection = glamorous.section({ margin: 1 })
<MyStyledSection>content</MyStyledSection>
// 渲染输出:<section class="<glamor-generated-class>">content</section>
// 应用的样式: {margin: 1}
GlamorousCompoennt
就是从glamorousComponentFactory返回的东西。他的工作就是收集所有的样式然后从glamor
)产生一个className
并把这个className
转交给你的React组件。
有时候你只是单纯的想写点样式而不关心组件叫什么名字(因为起名字是一件麻烦事)。所以glamorous给所有类型的DOM节点都提供了一个GlamorousComponent
,这样会让你更方便。
const { Div, Span, A, Img } = glamorous
function MyUserInterface({name, tagline, imageUrl, homepage, size}) {
const nameSize = size
const taglineSize = size * 0.5
return (
<Div display="flex" flexDirection="column" justifyContent="center">
<A href={homepage} textDecoration="underline" color="#336479">
<Img borderRadius="50%" height={180} src={imageUrl} />
<Div fontSize={nameSize} fontWeight="bold">{name}</Div>
</A>
<Span fontSize={taglineSize} color="#767676">
{tagline}
</Span>
</Div>
)
}
点击这里在你的浏览器中尝试一下
给每个组件命名是一个枯燥乏味的事情,所以这些预置的组件是很有用的!另一个很方便的地方就是你可以把样式当做属性传入。从上面的例子可以注意到,glamorous可以区分传入的属性是样式还是有语义的(比如对于Img
和A
组件src
和href
属性就有特殊意义)。
css
属性可以用来传入样式对象。
import glamorous, {withTheme} from 'glamorous'
const { Div, Span } = glamorous
const predefinedStyle = {
color: '#767676',
fontSize: 18,
}
const MyUserInterface = withTheme(function ({tagline, theme}) {
return (
<Div
css={{
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
[theme.mq.tablet]: {
flexDirection: 'row'
}
}}
>
<Span css={predefinedStyle}>
{tagline}
</Span>
</Div>
)
})
还有一个小技巧...下面的写法也是没问题的:
<glamorous.Div color="blue">
JSX is pretty wild!
</glamorous.Div>
使用属性最常见的场景就是重写现有的组件样式(通过glammorous
或者其他的方式生成)。结合glamorous()
函数使用className
,css
,和theme
或者简单的组件组合来实现重写。
如果你对使用theme
属性感兴趣的话可以看一看主题章节。在这个章节我们先来解释一下怎么使用className
,css
,和组件组合的方式来重写一个组件的样式。
让我们一起来看看下面的例子吧。
点击这里在你的浏览器中尝试一下
我们会用下面的这个组件作为演示用的GlamorousComponent
const MyStyledDiv = glamorous.div({margin: 1, fontSize: 1, padding: 1})
className
对于你提供的每个className
,GlamorousComponent
都会检查它是否是一个由glamor
生成的className
(可以从glamor或者glamorous
来,这并不重要)。如果是的话,就把产生这个className
的原始样式和已经渲染的样式合并,冲突的属性会优先保留重写样式中的。
对于不是glamor
生成的classNames
,就会和glamor
生成的连接起来。
const myCustomGlamorStyles = glamor.css({fontSize: 2})
<MyStyledDiv className={`${myCustomGlamorStyles} custom-class`} />
// 应用的样式
// {margin: 1, fontSize: 2, padding: 1}
// 和由类名custom-class提供的其他样式
css
这个预先设置的样式是一样的(比如在glamorous.div(...styles)
中传入的),如果使用了该属性的话,传入的样式在合并是有最高的优先级。
const myCustomGlamorStyles = glamor.css({fontSize: 2, padding: 2})
<MyStyledDiv
className={`${myCustomGlamorStyles} custom-class`}
css={{padding: 3}}
/>
// 应用的样式
// {margin: 1, fontSize: 2, padding: 3}
// 和由类名custom-class提供的其他样式
glamorous()
组合如果我们想扩展现存的组件样式的话,可以通过glamorous()
方法实现。
const MyComposedStyledDiv = glamorous(MyStyledDiv)({fontSize: 4, padding: 4})
<MyComposedStyledDiv />
// 应用的样式
// {margin: 1, fontSize: 4, padding: 4}
实际上,内置的DOM组件工厂只是提供了glamorous()
函数的抽象,所以glamorous.div
和glamorous('div')
两种写法的的效果是一样的。
glamorous的一个不错的好处就是他可以让你很明确的区分动态和静态样式,因为动态样式是用 函数的形式写的,静态样式是用对象字面量的形式写的。下面是一个同时使用动态样式和静态样式的例子:
const MyLink = glamorous.a(
{
color: 'blue',
textDecoration: 'none',
},
({size = 'small'}) => ({
fontSize: size === 'big' ? 24 : 16,
}),
// 你可以继续提供任意数量的参数
// `glamor`会把他们一起合并
// 当样式冲突的时候,最后传入的会保留。
)
render(
<div>
<MyLink href="#">Default is small</MyLink>
<br />
<MyLink href="#" size="big">size="big"</MyLink>
</div>
)
你可以在codesandbox中动态预览这个例子。
要用glamorous做动画的话,简单的可以用CSS transition做,如果是复杂的工作你可以通过glamor
的css.keyframes
API用keyframes
做。
// import * as glamor from 'glamor' // 定义动画的样式 const animationStyles = props => { const bounce = glamor.css.keyframes({ '0%': { transform: `scale(1.01)` }, '100%': { transform: `scale(0.99)` } }) return {animation: `${bounce} 0.2s infinite ease-in-out alternate`} } // 定义组件 const AnimatedDiv = glamorous.div(animationStyles) render( <AnimatedDiv> Bounce. </AnimatedDiv> )
React Native
glamorous
为React Native项目提供了一个特殊版本叫glamorous-native
npm install glamorous-native --save
你可以在glamorous-native项目了解更多。