(續)Css in js 一次實踐

前言

在上一章css in js 一次實踐中的末尾留了三個彩蛋:css

一、styled.div & styled('div') 有什麼區別html

二、模版字符串中的樣式是怎麼解析的?爲何能夠嵌套?react

三、爲何會返回一個組件?es6

本章就從源碼來簡單解釋一下。json

第一個問題

先看包裏的package.json,找到main字段bash

按照這個路徑去找入口,並無找到,若是有哪位小夥伴找到了,記得和我說一下。 既然主入口沒找到,那就去src下面的index裏找找看
進入這個文件,源碼是

// @flow
import type { Target } from '../types'
import domElements from '../utils/domElements'

export default (styledComponent: Function, constructWithOptions: Function) => {
  const styled = (tag: Target) => constructWithOptions(styledComponent, tag)

  // Shorthands for all valid HTML Elements
  domElements.forEach(domElement => {
    styled[domElement] = styled(domElement)
  })

  return styled
}
複製代碼

能夠看到,函數內定義了一個styled函數,接收一個Target類型的參數,這個Target類型定義是export type Target = string | ComponentType<*>,而這個ComponentType就是從react包裏導出的dom

type ComponentType<P = {}> = ComponentClass<P> | FunctionComponent<P>;函數

對應了React中兩種組件的定義方式(類定義和純函數定義)。接着看,註釋上說post

對全部有效的html元素創建快捷鍵,這個docElements裏定一個全部的html元素,遍ui

歷這個docElements元素,將html元素添加爲styled對象的屬性。至於這句

styled(domElement)

你們別忘了上面Target的類型定義裏前面還能夠接收一個string類型參數。至此,

第一個問題解決,styled.div 和 styled('div')沒有任何區別,styled.div只是style('div')的

快捷方式,可是 style.形式的使用只支持html元素,對React組件不適用,

因此,在爲組件定義樣式的時候仍是使用styled(ReactComponent)。

第二個問題

ES6裏標籤模版的形式,函數即標籤,模版緊跟在標籤後面做爲標籤的參數,也就是styled.div後面的模版字符串裏的內容做爲style.div函數的參數調用。 具體關於模版字符串的內容請參考阮一峯的ES6模版字符串

關於styled解決css嵌套問題,先貼一下css.js的代碼:

// @flow
import interleave from '../utils/interleave'
import isPlainObject from '../utils/isPlainObject'
import { EMPTY_ARRAY } from '../utils/empties'
import flatten from '../utils/flatten'
import type { Interpolation, RuleSet, Styles } from '../types'

export default (
  styles: Styles,
  ...interpolations: Array<Interpolation>
): RuleSet => {
  if (typeof styles === 'function' || isPlainObject(styles)) {
    // $FlowFixMe
    return flatten(interleave(EMPTY_ARRAY, [styles, ...interpolations]))
  }

  // $FlowFixMe
  return flatten(interleave(styles, interpolations))
}
複製代碼

css這個函數是做爲一個參數供style對象調用的,由於之間的關係太深,沒辦法貼出來,有興趣的小夥伴能夠本身去看一下。

能夠看到css.js返回了一個flatten函數,字面意思是拉伸、變平。這個函數的做用就是把嵌套的css變爲一層,Array.flat()函數。

第三個問題

其實第三個問題你們應該都能想到,沒錯,就是HOC(高階組件),利用高階組件的Prop將style傳遞給children,相似於這種:

const StyledComponent = (options) => (Target) => {
   
       return class extends React.Component{
           
           static displayName = ...(styled.Target)
           
           render(){
               const {styles} = options;
               const props = Object.assign({},this.props,{style:styles})
               return <Target {...props}/>
           }
       }
       
       
   }
複製代碼

結尾

時間倉促,並無將這個包很詳細的講一下(其實我不會。。。),這個包裏還有不少很好玩的東西,好比觀察者模式、發佈訂閱模式、once函數、curry函數等等。寫這篇的主要目的就是想要看看一個包是怎麼實現的,它裏面用到的思想和技巧可以對咱們產生很大的啓發,因此我建議小夥伴們在使用一個第三方的時候儘量的去看看人家是怎麼實現的?爲何這麼實現?這能快速提升咱們的思惟方式和coding能力。

最後,若是我有寫的不對的地方,歡迎指正,謝謝。

祝生活愉快。

相關文章
相關標籤/搜索