React style支持数组语法糖探究
使用react-native,挖土填坑,下一脚还是继续踩坑。踩坑之余也发现了和react不同之处,或可称之为小亮点。话说三句不能离代码,请赏下文:
class demo extends Component {
render() {
const btnText = {
fontSize: 30,
color: '#757575'
}
const color = {
color: '#FE2740'
}
return (
<TouchableOpacity
style={styles.wordContainer}
activeOpacity={1}
onPress={()=>this.props.showWordDialog(index, item)}>
<Text style={
Object.assign({},
btnText,
item === selectedWord && color
)}
>
Button
</Text>
</TouchableOpacity>
)
}
}
在rn中样式通过style属性,其实就是一个样式对象,可以理解为内联样式。
常见的需求,静态一套样式,交互后需要修改样式或者新增样式。使用rn初期,便想到style支持对象,结合jsx特性,使用Object.assign进行浅拷贝,合成一个对象。
此种解决方案并无问题,使用良久,仍是不能习惯每次出现出现此类情况,需要格式代码洋洋洒洒好几行,懒惰使人进步,如何才能更少的代码,行数实现?
直到某次项目预研时,发现了rn的神奇写法(也许文档翻的还是不够烂,大佬勿喷),如下所示:
class demo extends Component {
render() {
const btnText = {
fontSize: 30,
color: '#757575'
}
const color = {
color: '#FE2740'
}
return (
<TouchableOpacity
style={styles.wordContainer}
activeOpacity={1}
onPress={()=>this.props.showWordDialog(index, item)}>
<Text style={[btnText, item === selectedWord && color}]}>
Button
</Text>
</TouchableOpacity>
)
}
}
当你需要设置多个样式时,rn style支持对象数组,你可以在里面增加判断,乃至多个样式对象,以最右侧值优先。如此写法又可以少敲多少代码!!!
尝到甜头之后则想react是否可以实现一波,源码扒一下,发现海量源码难以下咽。转念一想,先写成数组,看看报错会出在哪里?
立马去react中尝试一波,结果:
秉着不抛弃不放弃的精神,为了少写代码让我们低头看报错。
根据报错第一条信息,此时镜头给到了react-dom中4619行的setValueForStyles方法,瞅瞅这命名基本了解一切有没有,给styles设置值!!!上代码:
/**
* Sets the value for multiple styles on a node. If a value is specified as
* '' (empty string), the corresponding style property will be unset.
*
* @param {DOMElement} node
* @param {object} styles
*/
function setValueForStyles(node, styles) {
var style = node.style;
for (var styleName in styles) {
if (!styles.hasOwnProperty(styleName)) {
continue;
}
var isCustomProperty = styleName.indexOf('--') === 0;
{
if (!isCustomProperty) {
warnValidStyle$1(styleName, styles[styleName]);
}
}
var styleValue = dangerousStyleValue(styleName, styles[styleName], isCustomProperty);
if (styleName === 'float') {
styleName = 'cssFloat';
}
if (isCustomProperty) {
style.setProperty(styleName, styleValue);
} else {
style[styleName] = styleValue;
}
}
}
从头看这个函数,两个参数node, styles,且第一行取的就是node.style,来我们猜猜这是不是我们传进来的style。验证结果没错,style传入就是在这里。
这里将我们传入的style进行拆分并验证是否正确,而我们传入的数组通过dangerousStyleValue的检测返回对象,并不能最后用于样式展示,所以最终引起报错。
这里我们便理明白了react中style为什么不支持对象数组类型。接下来只需稍加修改便可达成我们最终目标:少写代码!!!
上代码!!!
function setValueForStyles(node, styles) {
var style = node.style;
if (Array.isArray(styles)) {
styles = Object.assign({}, ...styles)
}
.....
}
如上所示在拿到传入的style之后进行类型检测,如果为数组类型,就将数组内的对象通过Object.assign配合es6扩展运算符整合成一个styles对象进行后续处理。一次assign众生受益。少写代码目标达成!!!