JSS與React的集成

介紹

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è)themeprop,使用一個(gè)objectfunction表示:
  • 如果它是一個(gè)Object并在根ThemeProvider中使用剂买,則它是完整的并向下傳遞到React Tree惠爽。
  • 如果它是Object并在嵌套的ThemeProvider中使用,則它將與父ThemeProvider的主題合并瞬哼,并向下傳遞到React Tree婚肆。
  • 如果它是Function并在嵌套的ThemeProvider中使用,則它將從父``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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市游岳,隨后出現(xiàn)的幾起案子政敢,更是在濱河造成了極大的恐慌,老刑警劉巖胚迫,帶你破解...
    沈念sama閱讀 219,039評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件喷户,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡访锻,警方通過(guò)查閱死者的電腦和手機(jī)褪尝,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,426評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)朗若,“玉大人恼五,你說(shuō)我怎么就攤上這事】扌福” “怎么了灾馒?”我有些...
    開封第一講書人閱讀 165,417評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)遣总。 經(jīng)常有香客問(wèn)我睬罗,道長(zhǎng)轨功,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,868評(píng)論 1 295
  • 正文 為了忘掉前任容达,我火速辦了婚禮古涧,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘花盐。我一直安慰自己羡滑,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,892評(píng)論 6 392
  • 文/花漫 我一把揭開白布算芯。 她就那樣靜靜地躺著柒昏,像睡著了一般。 火紅的嫁衣襯著肌膚如雪熙揍。 梳的紋絲不亂的頭發(fā)上职祷,一...
    開封第一講書人閱讀 51,692評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音届囚,去河邊找鬼有梆。 笑死,一個(gè)胖子當(dāng)著我的面吹牛意系,可吹牛的內(nèi)容都是我干的泥耀。 我是一名探鬼主播,決...
    沈念sama閱讀 40,416評(píng)論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼蛔添,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼爆袍!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起作郭,我...
    開封第一講書人閱讀 39,326評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎弦疮,沒(méi)想到半個(gè)月后夹攒,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,782評(píng)論 1 316
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡胁塞,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,957評(píng)論 3 337
  • 正文 我和宋清朗相戀三年咏尝,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片啸罢。...
    茶點(diǎn)故事閱讀 40,102評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡编检,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出扰才,到底是詐尸還是另有隱情允懂,我是刑警寧澤,帶...
    沈念sama閱讀 35,790評(píng)論 5 346
  • 正文 年R本政府宣布衩匣,位于F島的核電站蕾总,受9級(jí)特大地震影響粥航,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜生百,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,442評(píng)論 3 331
  • 文/蒙蒙 一递雀、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧蚀浆,春花似錦缀程、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,996評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至秕衙,卻和暖如春蠢甲,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背据忘。 一陣腳步聲響...
    開封第一講書人閱讀 33,113評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工鹦牛, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人勇吊。 一個(gè)月前我還...
    沈念sama閱讀 48,332評(píng)論 3 373
  • 正文 我出身青樓曼追,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親汉规。 傳聞我的和親對(duì)象是個(gè)殘疾皇子礼殊,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,044評(píng)論 2 355