介紹
React-JSS使用新的Hooks API將JSS與React集成在一起砰奕。 JSS和默認(rèn)預(yù)設(shè)已經(jīng)內(nèi)置墩朦。
從v10開始,不支持基于HOC的API碗降,并將在所有即將發(fā)布的主要版本中將其刪除匿又。如下的使用方式將不支持方灾。
import React from 'react'
import {render} from 'react-dom'
import withStyles from 'react-jss'
// 1、創(chuàng)建styles
const styles = {
...
}
// 2碌更、使用這些樣式定義組件裕偿,并將其傳遞給classes屬性,使用它來(lái)分配作用域類名
const Button = ({classes, children}) => (
<button className={classes.myButton}>
<span className={classes.myLabel}>{children}</span>
</button>
)
// 3针贬、最后击费,將樣式表注入組件
const StyledButton = withStyles(styles)(Button)
// 或 4、導(dǎo)出組件
export default withStyles(styles)(Button)
// 5桦他、使用
const App = () => <StyledButton>Submit</StyledButton>
render(<App />, document.getElementById('root'))
與直接使用核心JSS軟件包相比蔫巩,其好處是:
- 動(dòng)態(tài)主題-允許基于上下文的主題傳播和運(yùn)行時(shí)更新。
- 關(guān)鍵CSS提取-僅從呈現(xiàn)的組件中提取CSS快压。
- 惰性評(píng)估-樣式表是在安裝組件時(shí)創(chuàng)建的圆仔,而在卸載組件時(shí)被刪除的。
- 樣式表的靜態(tài)部分將在所有元素之間共享蔫劣。
- 函數(shù)值和規(guī)則會(huì)隨你傳遞給useStyles(data)的任何數(shù)據(jù)自動(dòng)更新坪郭。例如,你可以傳遞道具脉幢,狀態(tài)或上下文中的任何內(nèi)容歪沃。
基本使用
import React from 'react'
import {render} from 'react-dom'
import {createUseStyles} from 'react-jss'
// 1嗦锐、創(chuàng)建樣式
const useStyles = createUseStyles({
myButton: {
color: 'green',
margin: {
// jss-plugin-expand插件讓語(yǔ)法可讀性更高
top: 5, // jss-plugin-default-unit插件補(bǔ)全單位
right: 0,
bottom: 0,
left: '1rem'
},
'& span': {
// jss-plugin-nested 插件將樣式應(yīng)用到子節(jié)點(diǎn)
fontWeight: 'bold' // jss-plugin-camel-case插件將fontWegith轉(zhuǎn)化為font-weight
}
},
myLabel: {
fontStyle: 'italic'
},
})
// 2、使用這些樣式定義組件沪曙,并將其傳遞給classes屬性奕污,使用它來(lái)分配作用域類名
const Button = ({children}) => {
const classes = useStyles() // 使用樣式
return (
<button className={classes.myButton}>
<span className={classes.myLabel}>{children}</span>
</button>
)
}
// 3、使用組件
const App = () => <Button>Submit</Button>
render(<App />, document.getElementById('root'))
上面的代碼編譯為
<div id="root">
<button class="Button-myButton-0-1-24">
<span class="myLabel-0-1-87">
Submit
</span>
</button>
</div>
.myButton-0-1-24 {
color: green;
margin: 5px 0 0 1rem;
}
.myButton-0-1-24 span {
font-weight: bold;
}
.myLabel-0-1-87 {
font-style: italic;
}
動(dòng)態(tài)值
你可以直接使用函數(shù)值液走,函數(shù)規(guī)則和可觀察對(duì)象碳默。一旦組件第一次接收到新的props或mount,函數(shù)值和函數(shù)規(guī)則將接收props對(duì)象缘眶。
注意事項(xiàng):
首先呈現(xiàn)靜態(tài)屬性嘱根,以便函數(shù)值具有更高的源順序特異性:
import React from 'react'
import {createUseStyles} from 'react-jss'
const useStyles = createUseStyles({
myButton: {
padding: props => props.spacing
},
myLabel: props => ({
display: 'block',
color: props.labelColor,
fontWeight: props.fontWeight,
fontStyle: props.fontStyle
})
})
const Button = ({children, ...props}) => {
const classes = useStyles(props)
return (
<button className={classes.myButton}>
<span className={classes.myLabel}>{children}</span>
</button>
)
}
Button.defaultProps = {
spacing: 10,
fontWeight: 'bold',
labelColor: 'red'
}
const App = () => <Button fontStyle="italic">Submit</Button>
上面的代碼編譯為
<div id="root">
<button class="Button-myButton-1-25">
<span class="Button-myLabel-1-26">
Submit
</span>
</button>
</div>
.Button-myButton-1-25 {
padding: 10px;
}
.Button-myLabel-1-26 {
display: block;
color: red;
font-weight: bold;
font-style: italic;
}
主題化
主題化指定義一個(gè)主題,用ThemeProvider
包裝應(yīng)用程序巷懈,然后將主題對(duì)象傳遞給ThemeProvider
该抒。稍后,你可以在樣式創(chuàng)建器函數(shù)(createUseStyles ((theme) => { ... })
)中使用useTheme()
掛鉤來(lái)訪問(wèn)主題砸喻。之后柔逼,你可以更改主題,所有組件都將自動(dòng)獲得新主題割岛。
在幕后,react-jss為React使用了獨(dú)立的主題解決方案犯助。你可以在其回購(gòu)中找到完整的文檔癣漆。
ThemeProvider
的用法:
- 它有一個(gè)
theme
prop,使用一個(gè)object
或function
表示:
- 如果它是一個(gè)
Object
并在根ThemeProvider
中使用剂买,則它是完整的并向下傳遞到React Tree
惠爽。- 如果它是Object并在嵌套的
ThemeProvider中
使用,則它將與父ThemeProvider
的主題合并瞬哼,并向下傳遞到React Tree
婚肆。- 如果它是
Function
并在嵌套的ThemeProvide
r中使用,則它將從父``ThemeProvider應(yīng)用于主題坐慰。如果結(jié)果是一個(gè)
Object较性,它將沿著
React Tree```向下傳遞,否則拋出结胀。
-
ThemeProvider
和其他所有組件一樣赞咙,只能渲染一個(gè)child
,因?yàn)樗阡秩局惺褂?code>React.Children.only糟港,否則拋出攀操。
import React from 'react'
import {createUseStyles, useTheme, ThemeProvider} from 'react-jss'
// 1、當(dāng)有很多主題依賴關(guān)系時(shí)秸抚,最好使用theme函數(shù)
let useStyles = createUseStyles(theme => ({
button: {
background: theme.colorPrimary
},
label: {
fontWeight: 'bold'
}
}))
// 或者如果只有很少的主題相關(guān)樣式速和,則使用函數(shù)值可能會(huì)更好歹垫,并且props或state也用于其他值
useStyles = createUseStyles({
button: {
background: ({theme}) => theme.colorPrimary
},
label: {
fontWeight: 'bold'
}
})
// 2、定義組件颠放,傳入theme排惨、props等
const Button = ({children, ...props}) => {
const theme = useTheme()
const classes = useStyles({...props, theme})
return (
<button className={classes.button}>
<span className={classes.label}>{children}</span>
</button>
)
}
const theme = {
colorPrimary: 'green'
}
// 定義主題及使用組件
const App = () => (
<ThemeProvider theme={theme}>
<Button>I am a button with green background</Button>
</ThemeProvider>
)
使用自定義主題上下文
使用命名空間主題,這樣一組UI組件就不會(huì)與其他庫(kù)中的另一組UI組件發(fā)生沖突(也可以使用react-jss
)慈迈,或者如果你想從應(yīng)用程序中已使用的另一個(gè)上下文中使用同一主題若贮,則不會(huì)發(fā)生沖突。
import React from 'react'
import {createUseStyles, createTheming} from 'react-jss'
const ThemeContext = React.createContext({})
// 創(chuàng)建一個(gè)具有命名空間的主題對(duì)象
const theming = createTheming(ThemeContext)
// 注意這里的useTheme來(lái)自theming對(duì)象痒留,而不是來(lái)自react-jss導(dǎo)入谴麦。
const {ThemeProvider, useTheme} = theming
const useStyles = createUseStyles(
{
button: {
background: ({theme}) => theme.colorPrimary
}
// 將theming對(duì)象傳遞給createUseStyles()
},
{theming}
)
const myTheme = {
colorPrimary: 'green'
}
const Button = ({children, ...props}) => {
const theme = useTheme()
const classes = useStyles({...props, theme})
return <button className={classes.button}>{children}</button>
}
const OtherLibraryThemeProvider = () => null
const OtherLibraryComponent = () => null
const otherLibraryTheme = {}
// 使用具有命名空間的主題ThemeProviders-它們可以以任何順序嵌套
const App = () => (
<OtherLibraryThemeProvider theme={otherLibraryTheme}>
<OtherLibraryComponent />
<ThemeProvider theme={myTheme}>
<Button>Green Button</Button>
</ThemeProvider>
</OtherLibraryThemeProvider>
)
類名生成器選項(xiàng)
確保在服務(wù)器和客戶端上使用相同的設(shè)置。ID生成器用于類名和關(guān)鍵幀伸头。
1匾效、你可以通過(guò)傳遞自定義生成器函數(shù)來(lái)更改類名稱生成算法。
import React from 'react'
import ReactDOM from 'react-dom'
import {JssProvider} from 'react-jss'
import MyApp from './MyApp'
const generateId = (rule, sheet) => 'some-id'
ReactDOM.render(
<JssProvider generateId={generateId}>
<MyApp />
</JssProvider>,
document.getElementById('root')
)
2恤磷、你可以為每個(gè)類添加其他前綴面哼,詳見。
3扫步、你可以通過(guò)傳遞id
屬性來(lái)最小化類名魔策,詳見。
import React from 'react'
import ReactDOM from 'react-dom'
import {JssProvider} from 'react-jss'
import MyApp from './MyApp'
ReactDOM.render(
<JssProvider id={{minify: true}}>
<MyApp />
</JssProvider>,
document.getElementById('root')
)
服務(wù)端渲染
掛載應(yīng)用程序后河胎,應(yīng)刪除關(guān)鍵CSS呈現(xiàn)的服務(wù)器端使用的樣式標(biāo)簽闯袒。
import React from 'react'
import {renderToString} from 'react-dom/server'
import {JssProvider, SheetsRegistry, createGenerateId} from 'react-jss'
import MyApp from './MyApp'
export default function render(req, res) {
const sheets = new SheetsRegistry()
const generateId = createGenerateId()
const body = renderToString(
<JssProvider registry={sheets} generateId={generateId}>
<MyApp />
</JssProvider>
)
//任何在<MyApp />中使用useStyles的實(shí)例都將獲得樣式表
return res.send(
renderToString(
<html lang="en">
<head>
<style type="text/css">{sheets.toString()}</style>
</head>
<body>{body}</body>
</html>
)
)
}
參考
JSS