除了传统的 CSS,你还可以使用
内联样式
和
CSS-in-JS
作为 React 应用程序的样式选项。
对于内联样式,你可以将 JavaScript对象传递给样式属性:
const myStyle = {
fontSize: 24,
lineHeight: '1.3em',
fontWeight: 'bold',
};
Hello World!
然而,并非所有 CSS 特性都受支持。
另一方面,CSS-in-JS 是一种使用 JavaScript来设置组件样式的技术。在解析此 JavaScript时,会生成 CSS(通常作为
元素)并附加到 DOM 中。
这个功能由第三方库实现。例如,下面是使用
实现的上一个示例:
import { StyleSheet, css } from 'aphrodite';
const styles = StyleSheet.create({
myStyle: {
fontSize: 24,
lineHeight: '1.3em',
fontWeight: 'bold',
}
});
Hello World!
其他第三方库推荐:
我并不完全赞成使用 CSS-in-JS,但我不得不说,其中一些库增加了对在某些情况下可能会有用的功能支持。
在这篇文章中,我将讨论在 CSS-in-JS 中你可以用上面的库来做的五件事,而我打赌这是你不知道的。
1.参照其他样式组件
像
和
库允许您使用
从样式中创建 React 组件:
import styled from 'styled-components';
// Create a component that renders a
element with blue text
const BlueText = styled.p`
color: blue;
`;
My blue text
它们也允许你定位于其他样式组件(像你使用 CSS 选择器一样):
const ImportantText = styled.div`
font-weight: bold;
`;
const Text = styled.div`
color: gray;
${ImportantText} {
font-style: italic;
}
`;
render(
Text in gray
Important text in gray, bold and italic
Important text bold
);
这在组合伪类时很有用,例如,在悬停时更改组件的颜色:
const Text = styled.div`
color: gray;
&:hover ${ImportantText} {
color: red;
}
`;
2.使用JSS(或其他库)扩展某些库的特性
假设你已经使用
为你的应用程序设计样式,现在你需要支持主题。
但问题是
不能轻易地支持主题。 至少不像
那么容易。
不过,这里有两个项目将
JSS
的核心与
Aphrodite
和
styled-components
相结合,
和
。
通过这种方式,你可以保留
Aphrodite
(或
styled-components
) 的优点,并使用
JSS
的所有特性和
,从
到
,以及
,主题包,以下是它提供的高阶组件:
ThemeProvider
:通过 context 向 react 树传递主题对象。
withTheme
:允许你接收一个主题对象并作为属性来更新。
例如:
const blackTheme = {
color: 'black',
};
const App = () => (
);
在
Aphrodite
和主题的案例中,作为另一个例子,你也可以使用
,它有实现
或
接口,这样在定义样式时就可以访问主题信息了。
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
中,您可以使用
组件来渲染具有全局样式的样式元素。 例如:
body: {
fontFamily: 'Arial, Helvetica, sans-serif'
}
}}
/>
将返回:
body {
font-family: 'Arial, Helvetica, sans-serif';
}
JSS
使用一个
来编写全局样式:
const styles = {
'@global': {
body: {
fontFamily: 'Arial, Helvetica, sans-serif'
}
}
}
在
Aphrodite
中,你可以用
来做:
import {injectGlobalStyles} from "aphrodite-globals";
injectGlobalStyles({
"body": {
fontFamily: 'Arial, Helvetica, sans-serif',
}
});
或者通过
来使用
JSS
全局插件。
5.在单元测试中使用样式测试组件
有些库包含用于测试组件样式的工具。
Aphrodite
提供了一个没有文档说明(至少在写这篇文章的时候是这样)的对象
,它仅适用于非生产环境(
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
是另一个例子。它有一个
对象,用于在测试期间使用
clearState
,
enable
和
disable
方法控制内部状态和行为。
在
,您可以找到如何使用它的示例。
结论
CSS-in-JS 是一种使用 JavaScript为应用程序设置样式的技术,你可以使用实现它的库来做有趣的事情。
在这篇文章中,我向你展示了5件你可能不知道可以使用这些库来做的事情。当然,并不是所有的库都是对等的,有些情况只适用于特定的库。
在这个
中,您可以测试和比较许多 CSS-in-JS 的库。
另一方面,还有其他库正在进一步采用 CSS,JavaScript和类型的概念。
其中一个库是
,一个基于组件的库,带有一个预处理器,可以将 stylable 的 CSS 转换成最小的跨浏览器的 vanilla CSS。