CSS in JS 很棒, 可是如何方便的處理僞類(Pseudo-classes)? react-dom-pseudo 提供一個相似 react-motion
方式的組件,方便的爲 react-dom
對象提供相似 CSS 的僞類.css
咱們首先用 npm
安裝:react
$ npm install --save react-dom-pseudo
複製代碼
react-dom-pseudo 支持如下僞類:git
Props | 模擬僞類 | 說明 | 默認值 | 必須 |
---|---|---|---|---|
merge | 是否使用 style 和 其餘狀態的 style 進行合併 | true | 否 | |
disable | 是否取消事件監聽 | false | 否 | |
style | 默認樣式 | undefined | 否 | |
linkStyle | :link | 未被點擊以前的樣式 | undefined | 否 |
visitedStyle | :visited | 被點擊過的樣式 | undefined | 否 |
focusStyle | :focus | input 等類型元素 onFocus 時的樣式 | undefined | 否 |
hoverStyle | :hover | 鼠標移入時顯示的樣式 | undefined | 否 |
activeStyle | :active | 鼠標或者觸屏點擊時的樣式 | undefined | 否 |
disableStyle | 當取消事件監聽時的樣式 | undefined | 否 | |
alwayStyle | 會和全部樣式合併,而且覆蓋重複的樣式屬性 | undefined | 否 |
他們會根據事件的觸發,和 style
合併返回, 如 {...style, ...activeStyle}
, 只有存在的樣式會進行合併github
樣式的組合規則: {...style, ...linkStyle, ...eventStyle, ...disableStyle, ...alwayStyle}
spring
import Pseudo from 'react-dom-pseudo';
export default () => {
return (
<div> <div>example:</div> <Pseudo style={sheet.input} hoverStyle={sheet.inputHover} focusStyle={sheet.inputFocus} > {events => <input {...events} />} </Pseudo> </div> ); }; // CSS in js const sheet = { input: { fontSize: '14px', border: '1px solid rgba(0,0,0,0)', background: '#f3f3f3', // 啓用過渡動畫 transition: 'all 0.2s ease-out', }, inputHover: { background: '#f0f0f0', }, inputFocus: { border: '1px solid rgba(0,0,0,0.1)', background: '#f0f0f3', transitionTimingFunction: 'ease-in', }, }; 複製代碼
Pseudo 的 renderProps 中包含如下事件npm
若是項目在移動端執行,就會把 onMouse?
相關的事件替換成 onTouch?
以兼容移動端react-native
Input
組件有什麼優點?咱們先看看若是咱們直接定義一個 Input 組件,來模擬 :hover 僞類數組
// 如下代碼直接在 markdown 中編寫,並沒有通過運行,僅用於闡述觀點
class Input extend React.Component {
state = {
hover: false
}
handleMouseEnter = ()=>{
this.setState({ hover: true });
}
handleMouseLeave = ()=>{
this.setState({ hover: false });
}
render(){
return <input style={this.state.hover?{...this.props.style, ...this.props.hoverStyle}:this.props.style} onMouseEnter={this.handleMouseEnter} onMouseLeave={this.handleMouseLeave} /> } } 複製代碼
而後咱們在項目中使用:sass
<Input style={inputStyle} hover={inputHoverStyle} />
複製代碼
一切看起來不錯,可是它不利於擴展, 例如:咱們若是須要給一個 div
或 SignButton
也添加以上功能,咱們須要再寫一個以上組件markdown
固然,咱們也能夠使用 HOC 的方式, 編寫一個 withHover
的組件, 即使如此,也須要在使用以前建立一個新的組件:
const SignButton = withHover(SignButton);
複製代碼
對比之下,就沒有 RenderProps
的方式優雅:
<Pseudo style={inputStyle} hoverStyle={inputHoverStyle}>
{events => <input {...events} />} </Pseudo>
<Pseudo style={inputStyle} hoverStyle={inputHoverStyle}>
{events => <div {...events} />} </Pseudo>
<Pseudo style={inputStyle} hoverStyle={inputHoverStyle}>
{events => <SignButton {...events} />} </Pseudo>
複製代碼
react-dom-pseudo
還能夠更簡化麼?因爲若是子對象是一個 div
或是一個 數組
時,以爲使用 childrenFuncion
的意義不大,因此能夠把簡寫:
// 能夠簡寫成以下, 此時 Pseudo 是一個 div組件
<Pseudo style={inputStyle} hoverStyle={inputHoverStyle} />
// 同理,多個子元素,也能夠這樣
<Pseudo style={inputStyle} hoverStyle={inputHoverStyle}>
<p>多個子元素</p>
<img src="xxx"/>
<div>父級至關於一個div</div>
</Pseudo>
複製代碼
renderProps 的參數還有第二個,是 Pseudo
內部的 state
, 咱們能夠獲取它以後作其餘事件, 以下面的例子,根據 hover 的狀態咱們修改 div
的 innerText
,
state 有 4 個對象 { hover, focus, active, visited }
<Pseudo style={inputStyle} hoverStyle={inputHoverStyle}>
{(events, state) => {
const mouseState = state.hover ? 'mouseIn' : 'mouseOut';
return <div {...events}>{mouseState}</div>;
}}
</Pseudo>
複製代碼
Pseudo 把 disable
設置成 true
<Pseudo disable />
複製代碼
Pseudo 有一個 alwayStyle
屬性,最終返回的樣式是這樣的 {...style, ...otherStyle, ...alwayStyle}
<Pseudo alwayStyle={style} />
複製代碼
因人而異,我以爲比寫 css
和 sass
更好一些,其緣由有如下幾點:
react-motion
, react-spring
等,都會須要操做 style 對象, 它的樣式可能分別會存在 css 和 js 中,此時就沒有 CSS in JS 簡潔;如何解決一些 CSS in JS 寫起來麻煩的事情?
sass
的顏色混合等功能,能夠使用 mix-color
之類的庫輕鬆解決;sass
的自定義變量,在 CSS in JS 中能夠很輕鬆的定義一個 globalStyles
對象達到;react-dom-pseudo
解決.react-dom-pseudo
支持 react-native
嗎?因爲 react-dom-pseudo
用到了 ReactDOM
的事件,因此不支持 react-native
, 有須要的朋友能夠 fork 一份把DOM事件改爲RN的 touchble
事件
最後,謝謝閱讀:)