styled-components 背后的魔法

styled-components 定义组件的风格为

 const Button = styled.button`
background-color: papayawhip;
border-radius: 3px;
color: palevioletred;
`

这个Button变量现在是一个React组件,可以像其他React组件一样渲染!那么它是如果实现的?

模板字符串

事实证明,这个奇怪的 styled.button`` 符号实际上是 ES6中引入的一种名为 Tagged Template Literal(模板字符串) 的新功能。

从本质上讲, styled.button``styled.button()都是调用一个函数,但当你传入参数以后,就会发现 我们不一样、不一样、不一样 !

那么让我们创建一个简单的函数来看看哪里不一样:

 const logArgs = (...args) => console.log(...args)

您可以在控制台中执行代码查看结果

 logArgs('a', 'b')
// -> a b logArgs``
// -> [""] logArgs`I like pizza`
// -> ["I like pizza"]

显而易见,正常调用输出的是一个字符串,而以模板字符串的方式调用输出的是一个数组。

那当我们传入字符串插值以后会发生什么呢?

 const favoriteFood = 'pizza'

 logArgs(`I like ${favoriteFood}.`)
// -> I like pizza. logArgs`I like ${favoriteFood}.`
// -> ["I like ", "."] "pizza"

Amazing,我们得到了一个数组和一个字符串,第一个参数是被插值分割而生成的数组,第二个参数就是插值

styled-components 背后的魔法

那当我们传入函数时,又会怎样?

 logArgs(`Test ${() => console.log('test')}`)
// -> Test () => console.log('test') logArgs`Test ${() => console.log('test')}`
// -> ["Test", ""] () => console.log('test')

你应该猜到了第二行输出的是一个字符串,第五行是一个数组和一个真正的函数。

我们来验证一下

 const execFuncArgs = (...args) => args.forEach(arg => {
if (typeof arg === 'function') {
arg()
}
}) execFuncArgs('a', 'b')
// -> undefined execFuncArgs(() => { console.log('this is a function') })
// -> "this is a function" execFuncArgs('a', () => { console.log('another one') })
// -> "another one" execFuncArgs(`Hi, ${() => { console.log('Executed!') }}`)
// -> undefined execFuncArgs`Hi, ${() => { console.log('Executed!') }}`
// -> "Executed!"

应用场景

以 Button 大小为例

 const Button = styled.button`
font-size: ${props => props.primary ? '2em' : '1em'};
` // font-size: 2em;
<Button primary /> // font-size: 1em;
<Button />

Refers

 
上一篇:binding与属性


下一篇:iOS开发必会的坐标系探究