React style支持数组语法糖

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中尝试一波,结果:

image-20200813212329670

秉着不抛弃不放弃的精神,为了少写代码让我们低头看报错。

根据报错第一条信息,此时镜头给到了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众生受益。少写代码目标达成!!!

posted @ 2020-08-13 23:53  Marphy  阅读(1368)  评论(0编辑  收藏  举报