框架 - 敏捷的CSS-IN-JS支持服務器端渲染,瀏覽器前綴和最小CSS生成。
支持將樣式與JavaScript組件共同關閉。
:hover
:active
等,無需將懸停或活動狀態存儲在組件中。 :visited
工作也很好。@font-face
檢測和插入。Aphrodite通過NPM分佈:
npm install --save aphrodite
如果您想觀看介紹性視頻,則可以在這裡找到它們。
import React , { Component } from 'react' ;
import { StyleSheet , css } from 'aphrodite' ;
class App extends Component {
render ( ) {
return < div >
< span className = { css ( styles . red ) } >
This is red.
< / span >
< span className = { css ( styles . hover ) } >
This turns red on hover.
< / span >
< span className = { css ( styles . small ) } >
This turns red when the browser is less than 600px width.
< / span >
< span className = { css ( styles . red , styles . blue ) } >
This is blue.
< / span >
< span className = { css ( styles . blue , styles . small ) } >
This is blue and turns red when the browser is less than
600px width.
< / span >
< / div > ;
}
}
const styles = StyleSheet . create ( {
red : {
backgroundColor : 'red'
} ,
blue : {
backgroundColor : 'blue'
} ,
hover : {
':hover' : {
backgroundColor : 'red'
}
} ,
small : {
'@media (max-width: 600px)' : {
backgroundColor : 'red' ,
}
}
} ) ;
注意:如果您想有條件使用樣式,則可以通過以下方式完成。
const className = css (
shouldBeRed ( ) ? styles . red : styles . blue ,
shouldBeResponsive ( ) && styles . small ,
shouldBeHoverable ( ) && styles . hover
)
< div className = { className } > Hi < / div>
這是可能的,因為任何虛假的論點都將被忽略。
要結合樣式,請將多種樣式或樣式的陣列傳遞到css()
中。從所有者組成部分組合樣式時,這很常見:
class App extends Component {
render ( ) {
return < Marker styles = { [ styles . large , styles . red ] } / > ;
}
}
class Marker extends Component {
render ( ) {
// css() accepts styles, arrays of styles (including nested arrays),
// and falsy values including undefined.
return < div className = { css ( styles . marker , this . props . styles ) } / > ;
}
}
const styles = StyleSheet . create ( {
red : {
backgroundColor : 'red'
} ,
large : {
height : 20 ,
width : 20
} ,
marker : {
backgroundColor : 'blue'
}
} ) ;
reset
功能可用於重置HTML樣式標籤,注入緩衝區和注入的緩存。當需要撕下阿芙羅狄蒂並備份時,有用。
import { reset } from 'aphrodite' ;
reset ( ) ;
雖然可以使用resetInjectedStyle
函數重置單個密鑰(通常是類名稱)的注射緩存。
import { resetInjectedStyle } from 'aphrodite' ;
resetInjectedStyle ( 'class_1sAs8jg' ) ;
要執行服務器端渲染,請致電StyleSheetServer.renderStatic
,該儀表率進行回調。在回調內進行渲染,然後返回生成的HTML。將收集對回調內部css()
所有調用,並將返回生成的CSS以及生成的HTML。
補液讓Aphrodite知道已經插入了哪些樣式。如果您不補水,阿芙羅狄蒂可能會在頁面上添加重複樣式。
要執行補液,請致電StyleSheet.rehydrate
並使用StyleSheetServer.renderStatic
返回給您的生成類名稱的列表。
注意:如果您在項目中使用了aphrodite/no-important
,並且想在服務器端渲染它,請確保從aphrodite/no-important
中導入StyleSheetServer
,否則您將遇到錯誤。
例如:
import { StyleSheetServer } from 'aphrodite' ;
// Contains the generated html, as well as the generated css and some
// rehydration data.
var { html , css } = StyleSheetServer . renderStatic ( ( ) => {
return ReactDOMServer . renderToString ( < App / > ) ;
} ) ;
// Return the base HTML, which contains your rendered HTML as well as a
// simple rehydration script.
return `
<html>
<head>
<style data-aphrodite> ${ css . content } </style>
</head>
<body>
<div id='root'> ${ html } </div>
<script src="./bundle.js"></script>
<script>
StyleSheet.rehydrate( ${ JSON . stringify ( css . renderedClassNames ) } );
ReactDOM.render(<App/>, document.getElementById('root'));
</script>
</body>
</html>
` ;
!important
默認情況下,阿芙羅狄蒂(Aphrodite)將附加!important
。這旨在使與預先存在的代碼庫集成更加容易。如果您想避免這種aphrodite
,那麼而不是導入阿芙羅狄蒂aphrodite/no-important
。否則,用法是相同的:
import { StyleSheet , css } from 'aphrodite/no-important' ;
默認情況下,阿芙羅狄蒂(Aphrodite)將把樣式名稱縮小到其生產中的哈希( process.env.NODE_ENV === 'production'
)。您可以通過在調用StyleSheet.create
之前用true
或false
minify
縮放來覆蓋此行為。
例如,如果您想促進生產調試,這將很有用。
import { StyleSheet , minify } from 'aphrodite' ;
// Always keep the full style names
minify ( false ) ;
// ... proceed to use StyleSheet.create etc.
創建自定義字體面是一種特殊情況。通常,您需要定義全局@font-face
規則。在阿芙羅狄蒂(Aphrodite)的情況下,我們只想插入該規則,如果該規則實際上是由頁面中的類實際引用的。我們已經做到了,以便fontFamily
屬性可以接受字體 - 臉對象(直接或內部的數組內)。然後,基於字體定義生成全局@font-face
規則。
const coolFont = {
fontFamily : "CoolFont" ,
fontStyle : "normal" ,
fontWeight : "normal" ,
src : "url('coolfont.woff2') format('woff2')"
} ;
const styles = StyleSheet . create ( {
headingText : {
fontFamily : coolFont ,
fontSize : 20
} ,
bodyText : {
fontFamily : [ coolFont , "sans-serif" ]
fontSize : 12
}
} ) ;
Aphrodite將確保該字體的全局@font-face
規則僅插入一次,無論它被引用了多少次。
類似於字體的面孔,阿芙羅狄蒂(Aphrodite)支持關鍵幀動畫,但被視為特殊情況。一旦我們找到了引用動畫的實例,就會創建一個全局@keyframes
規則並將其附加到頁面上。
動畫以典型的@keyframes
時尚的形式提供作為描述動畫的對象。使用animationName
屬性,您可以提供單個動畫對像或動畫對像數組。可以作為字符串提供其他動畫屬性(例如animationDuration
。
const translateKeyframes = {
'0%' : {
transform : 'translateX(0)' ,
} ,
'50%' : {
transform : 'translateX(100px)' ,
} ,
'100%' : {
transform : 'translateX(0)' ,
} ,
} ;
const opacityKeyframes = {
'from' : {
opacity : 0 ,
} ,
'to' : {
opacity : 1 ,
}
} ;
const styles = StyleSheet . create ( {
zippyHeader : {
animationName : [ translateKeyframes , opacityKeyframes ] ,
animationDuration : '3s, 1200ms' ,
animationIterationCount : 'infinite' ,
} ,
} ) ;
Aphrodite將確保永遠不會重複@keyframes
規則,無論給出給定規則多少次。
阿芙羅狄蒂的構建是考慮到反應的,但不依賴於反應。在這裡,您可以看到它與Web組件一起使用:
import { StyleSheet , css } from 'aphrodite' ;
const styles = StyleSheet . create ( {
red : {
backgroundColor : 'red'
}
} ) ;
class App extends HTMLElement {
attachedCallback ( ) {
this . innerHTML = `
<div class=" ${ css ( styles . red ) } ">
This is red.
</div>
` ;
}
}
document . registerElement ( 'my-app' , App ) ;
Aphrodite將自動嘗試在文檔的<head>
元素中創建一個<style>
標籤,以將其生成的樣式放入中。Aphrodite只會生成一個<style>
標籤,並且隨著時間的推移會為此添加新樣式。如果您想控制Aphrodite使用哪種樣式標籤,請使用data-aphrodite
屬性創建樣式標籤,而Aphrodite將使用它而不是為您創建一個樣式。
為了加快樣式註入的速度,阿芙羅狄蒂將自動嘗試將其寫入此<style>
標籤,以便發生最少數量的DOM修改。
阿芙羅狄蒂(Aphrodite)使用盡快安排緩衝液沖洗。如果您在componentDidMount
或componentDidUpdate
中測量DOM Elements的尺寸,則可以使用setTimeout
或flushToStyleTag
來確保注入所有樣式。
import { StyleSheet , css } from 'aphrodite' ;
class Component extends React . Component {
render ( ) {
return < div ref = "root" className = { css ( styles . div ) } / > ;
}
componentDidMount ( ) {
// At this point styles might not be injected yet.
this . refs . root . offsetHeight ; // 0 or 10
setTimeout ( ( ) => {
this . refs . root . offsetHeight ; // 10
} , 0 ) ;
}
}
const styles = StyleSheet . create ( {
div : {
height : 10 ,
} ,
} ) ;
將字符串分配給content
屬性時,它需要CSS中的雙重或單個引號。因此,使用Aphrodite,您還必須提供值content
中的引號,以匹配其在CSS中的表示方式。
例如:
const styles = StyleSheet . create ( {
large : {
':after' : {
content : '"Aphrodite"' ,
} ,
} ,
} ,
small : {
':before' : {
content : "'Aphrodite'" ,
} ,
} ,
} ) ;
生成的CSS將是:
. large_im3wl1 : after {
content : "Aphrodite" !important ;
}
. small_ffd5jf : before {
content : 'Aphrodite' !important ;
}
在結合多種阿芙羅狄蒂樣式時,強烈建議您將所有樣式合併為單個呼叫css()
,並且不應結合Aphrodite輸出的生成的類名稱(通過字符串串聯, classnames
等)。例如,如果您有一種基本的foo
風格,則試圖用bar
覆蓋:
const styles = StyleSheet . create ( {
foo : {
color : 'red'
} ,
bar : {
color : 'blue'
}
} ) ;
// ...
const className = css ( styles . foo , styles . bar ) ;
const styles = StyleSheet . create ( {
foo : {
color : 'red'
} ,
bar : {
color : 'blue'
}
} ) ;
// ...
const className = css ( styles . foo ) + " " + css ( styles . bar ) ;
為什麼重要?儘管第二個將產生有效的類名稱,但不能保證bar
樣式將覆蓋foo
名稱。 CSS的工作方式,不是最重要的元素上的class名稱,而是特殊性。但是,當我們查看生成的CSS時,我們發現所有類名稱都具有相同的特異性,因為它們都是單個類名稱:
. foo_im3wl1 {
color : red;
}
. bar_hxfs3d {
color : blue;
}
在特異性相同的情況下,重要的是樣式出現在樣式表中的順序。也就是說,如果生成的樣式表看起來像
. foo_im3wl1 {
color : red;
}
. bar_hxfs3d {
color : blue;
}
然後,您將獲得bar
樣式的適當效果,使foo
,但是如果樣式表看起來像
. bar_hxfs3d {
color : blue;
}
. foo_im3wl1 {
color : red;
}
然後,我們最終會帶有相反的效果,並帶有foo
Ruperriding bar
!解決此問題的方法是將兩種樣式傳遞到Aphrodite的css()
調用中。然後,它將產生一個單個類名稱,例如foo_im3wl1-o_O-bar_hxfs3d
,並具有正確的覆蓋樣式,從而解決了問題:
. foo_im3wl1-o_O-bar_hxfs3d {
color : blue;
}
當在阿芙羅狄蒂(Aphrodite)中指定樣式時,它們在實際樣式表中出現的順序取決於從對像中檢索鍵的順序。此訂購由用於渲染樣式的JavaScript引擎確定。有時,樣式出現在樣式表中的順序對於CSS的語義而言。例如,根據引擎,從
const styles = StyleSheet . create ( {
ordered : {
margin : 0 ,
marginLeft : 15 ,
} ,
} ) ;
css ( styles . ordered ) ;
您可能希望生成以下CSS:
margin : 0 px ;
margin-left : 15 px ;
但是根據樣式對像中鍵的順序,CSS可能顯示為
margin-left : 15 px ;
margin : 0 px ;
語義上有所不同,因為後來出現的樣式將覆蓋其前面的樣式。
當服務器端渲染(如果生成的樣式以不同的順序出現在客戶端和服務器上的順序顯示)時,這也可能表現為一個問題。
如果您遇到此問題,其中樣式不會以它們出現在您的對像中的順序中出現在生成的CSS中,則有兩個解決方案:
不要使用速記屬性。例如,在上面的餘量示例中,通過使用速記屬性和相同樣式的長達屬性轉換為僅使用Longhand屬性,可以避免問題。
const styles = StyleSheet . create ( {
ordered : {
marginTop : 0 ,
marginRight : 0 ,
marginBottom : 0 ,
marginLeft : 15 ,
} ,
} ) ;
通過使用Map
指定樣式的訂購。由於Map
S保留其插入順序,因此Aphrodite能夠以正確的順序放置您的樣式。
const styles = StyleSheet . create ( {
ordered : new Map ( [
[ "margin" , 0 ] ,
[ "marginLeft" , 15 ] ,
] ) ,
} ) ;
請注意,在所有瀏覽器中並未完全支持Map
S。可以使用ES6-Shim之類的包裝來填充它。
可以使用擴展名添加額外的功能。
要向阿芙羅狄蒂添加擴展名,請使用您要添加的擴展名調用StyleSheet.extend
。結果將是一個包含Aphrodite( css
, StyleSheet
等)通常導出的對象,其中包含您的擴展名。例如:
// my-aphrodite.js
import { StyleSheet } from "aphrodite" ;
export default StyleSheet . extend ( [ extension1 , extension2 ] ) ;
// styled.js
import { StyleSheet , css } from "my-aphrodite.js" ;
const styles = StyleSheet . create ( {
...
} ) ;
注意:使用擴展可能會導致阿芙羅狄蒂的樣式無法正常工作。普通的阿芙羅狄蒂(Aphrodite)正確使用,可確保正確的樣式始終應用於元素。由於CSS特異性規則,擴展可能使您能夠生成相互衝突的樣式,從而顯示不正確的樣式。請參閱下面的全球擴展名,以查看可能出了什麼問題。
當前,只有一種擴展名:選擇器處理程序。這類擴展使您可以查看某人指定並基於它們生成新選擇器的選擇器。它們用於處理阿芙羅狄蒂內部的偽風格和媒體查詢。有關如何創建選擇器處理程序函數的信息,請參見defaultSelectorHandlers
文檔。
要使用擴展程序,請創建一個包含您創建的擴展名的鍵的對象,然後將其傳遞到StyleSheet.extend()
:
const mySelectorHandler = ... ;
const myExtension = { selectorHandler : mySelectorHandler } ;
const { StyleSheet : newStyleSheet , css : newCss } = StyleSheet . extend ( [ myExtension ] ) ;
例如,您可以編寫一個擴展程序,該擴展名生成像
const globalSelectorHandler = ( selector , _ , generateSubtreeStyles ) => {
if ( selector [ 0 ] !== "*" ) {
return null ;
}
return generateSubtreeStyles ( selector . slice ( 1 ) ) ;
} ;
const globalExtension = { selectorHandler : globalSelectorHandler } ;
但是,當兩個地方嘗試為同一全局選擇器生成樣式時,這可能會導致問題!例如,之後
const styles = StyleSheet . create ( {
globals : {
'*div' : {
color : 'red' ,
} ,
}
} ) ;
const styles2 = StyleSheet . create ( {
globals : {
'*div' : {
color : 'blue' ,
} ,
} ,
} ) ;
css ( styles . globals ) ;
css ( styles2 . globals ) ;
它不能確定DIV是紅色還是藍色。
通過將環境變量process.env.NODE_ENV
設置為字符串值production
來縮小類名稱。
StyleSheet.create
內容,並查看生成的CSS版權(C)2016 Khan Academy