CSS in JS 很棒, 但是如何方便的處理CSS偽類
不知道掘金至不支持GIF
CSS in JS 很棒, 但是如何方便的處理偽類(Pseudo-classes)? react-dom-pseudo 提供一個類似 react-motion 方式的組件,方便的為 react-dom 物件提供類似 CSS 的偽類.
我們首先用 npm 安裝:
$ npm install --save react-dom-pseudo
復制代碼
APIs
react-dom-pseudo 支持以下偽類:
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}, 只有存在的樣式會進行合并
樣式的組合規則: {...style, ...linkStyle, ...eventStyle, ...disableStyle, ...alwayStyle}
使用
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 中包含以下事件
onClick: 用來模擬 :link 和 :visited 偽類
onFocus\Blur: 用來模擬 :focus 偽類
onMouseEnter\Leave: 用來模擬 :hover 偽類
onMouseDown\Up: 用來模擬 :active 偽類
如果專案在移動端執行,就會把 onMouse? 相關的事件替換成 onTouch? 以兼容移動端
renderProps 的方式相比我直接定義一個 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} />
}
}
復制代碼
然后我們在專案中使用:
<Input style={inputStyle} hover={inputHoverStyle} />
復制代碼
一切看起來不錯,但是它不利于擴展, 例如:我們如果需要給一個 div 或 SignButton 也添加以上功能,我們需要再寫一個以上組件
當然,我們也可以使用 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="https://bbs.csdn.net/topics/xxx"/>
<div>父級相當于一個div</div>
</Pseudo>
復制代碼
我如何獲取 hover、active 等狀態,做除了樣式之外的其他事件?
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 in JS 好用么?
因人而異,我覺得比寫 css 和 sass 更好一些,其原因有以下幾點:
許多影片庫,如 react-motion, react-spring 等,都會需要操作 style 物件, 它的樣式可能分別會存在 css 和 js 中,此時就沒有 CSS in JS 簡潔;
CSS in JS 可以讓組件相關的代碼在一個檔案里閉合,我們修改一個組件時,不需要來回切換檔案;
如果我們專案較大,需要切分模塊,CSS in JS 會比傳統的 css 檔案更好和組件一起切分.
如何解決一些 CSS in JS 寫起來麻煩的事情?
sass 的顏色混合等功能,可以使用 mix-color 之類的庫輕松解決;
sass 的自定義變數,在 CSS in JS 中可以很輕松的定義一個 globalStyles 物件達到;
css 的偽類,以前用組件 state 的寫法撰寫起來比較麻煩、重復,可以用 react-dom-pseudo 解決.
react-dom-pseudo 支持 react-native 嗎?
由于 react-dom-pseudo 用到了 ReactDOM 的事件,所以不支持 react-native, 有需要的朋友可以 fork 一份把DOM事件改成RN的 touchble 事件
最后,謝謝閱讀:)
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/37214.html
標籤:HTML(CSS)
