【问题标题】:How to combine multiple inline style objects?如何组合多个内联样式对象?
【发布时间】:2015-07-10 20:09:20
【问题描述】:

在 React 中,您可以清楚地创建一个对象并将其指定为内联样式。即下面提到的。

var divStyle = {
  color: 'white',
  backgroundImage: 'url(' + imgUrl + ')',
  WebkitTransition: 'all', // note the capital 'W' here
  msTransition: 'all' // 'ms' is the only lowercase vendor prefix
};

var divStyle2 = {fontSize: '18px'};

React.render(<div style={divStyle}>Hello World!</div>, mountNode);

如何组合多个对象并将它们分配在一起?

【问题讨论】:

    标签: reactjs


    【解决方案1】:

    如果你使用 React Native,你可以使用数组表示法:

    <View style={[styles.base, styles.background]} />
    

    查看我的详细信息blog post。

    【讨论】:

    • 遗憾的是,您不能在常规 React 中执行此操作。
    • 如果您使用的是 React-Native,这应该是公认的答案
    • 您可以通过添加样式名称/值来稍微修改现有的内联样式。例如,&lt;View style={this.state.error == false ? styles.base : [styles.base, {backgroundColor: 'red'}]} /&gt;
    • 对于两种静态样式,在渲染函数之外执行StyleSheet.compose() 可能更有效。它将生成一个新的静态样式表,该样式表只会通过网桥发送一次。 (此建议不适用于在运行时更改的样式,或者内联而不是样式表中的样式。)
    【解决方案2】:

    您可以使用扩展运算符:

     <button style={{...styles.panel.button,...styles.panel.backButton}}>Back</button
    

    【讨论】:

    • 我收到“语法错误:意外标记”,指向第一个展开运算符中的第一个点。
    • @Izkata 你是在 react 还是 react native 中这样做,你能发布你的 sn-p
    • React,类似于&lt;div style={{ ...LEGEND_STYLE.box_base, ...{ 'background': '#123456' } }} /&gt;
    • 无论如何我都将其更改为使用像 &lt;div style={LEGEND_STYLE.box_gen('#123456')} 这样的辅助函数,所以对我来说没什么大不了的
    • 即使对象只有一个键值对也可以使用,即使扩展运算符只对可迭代对象有效!你能解释一下为什么吗? developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
    【解决方案3】:

    您可以使用Object.assign() 来做到这一点。

    在你的例子中,你会这样做:

    ReactDOM.render(
        <div style={Object.assign(divStyle, divStyle2)}>
            Hello World!
        </div>,
        mountNode
    );
    

    这将合并两种样式。如果有匹配的属性,第二个样式将替换第一个样式。

    正如 Brandon 所说,如果您想在不应用 fontSize 的情况下重用 divStyle,则应该使用 Object.assign({}, divStyle, divStyle2)。

    我喜欢用它来制作具有默认属性的组件。例如,这是一个带有默认 margin-right 的小无状态组件:

    const DivWithDefaults = ({ style, children, ...otherProps }) =>
        <div style={Object.assign({ marginRight: "1.5em" }, style)} {...otherProps}>
            {children}
        </div>;
    

    所以我们可以这样渲染:

    <DivWithDefaults>
        Some text.
    </DivWithDefaults>
    <DivWithDefaults className="someClass" style={{ width: "50%" }}>
        Some more text.
    </DivWithDefaults>
    <DivWithDefaults id="someID" style={{ marginRight: "10px", height: "20px" }}>
        Even more text.
    </DivWithDefaults>
    

    这会给我们结果:

    <div style="margin-right:1.5em;">Some text.</div>
    <div style="margin-right:1.5em;width50%;" class="someClass">Some more text.</div>
    <div style="margin-right:10px;height:20px;" id="someID">Even more text.</div>
    

    【讨论】:

    • 此解决方案可能会滥用Object.assign(),从而导致一些不良后果。请参阅the answer here 一个更可靠的解决方案。
    • 您的回答展示了一种滥用 Object.assign() 的方法。这对某些人来说可能是有用的信息,但不适用于我的示例。这个例子没有将默认值存储在对象中,对其进行变异,然后在其他地方重用变异的对象。
    • 不同意。您在答案中解决了使用Object.assign() 的两种不同方式。第一个,在前几句话中,是我发现的滥用的一个例子(即,如果 OP 做了你在第一个 code 块中的建议,他/她会变异 {divStyle})。第二种方式 - 即,将它包装在一个函数中,就像你拥有的那样,将起作用,但答案并没有明确表明你正在 解决 Object.assign() 的常见“问题” wrt 不变性(虽然我个人认为为每个默认组件编写自定义无状态函数有点麻烦)。
    • 哦,好的。确实如此。如果他想在不应用 fontSize 的情况下重用 divStyle ,则首先需要空对象。我会更新答案。
    • Object.assign() 是迄今为止实现连接的最方便的方法:)
    【解决方案4】:

    与 React Native 不同,我们不能在 React 中传递样式数组,比如

    <View style={[style1, style2]} />
    

    在 React 中,我们需要在将样式传递给样式属性之前创建单个样式对象。喜欢:

    const Header = (props) => {
      let baseStyle = {
        color: 'red',
      }
    
      let enhancedStyle = {
        fontSize: '38px'
      }
    
      return(
        <h1 style={{...baseStyle, ...enhancedStyle}}>{props.title}</h1>
      );
    }
    

    我们使用 ES6 Spread operator 来组合两种样式。您也可以将Object.assign() 用于相同目的。

    如果您不需要将样式存储在 var 中,这也可以使用

    <Segment style={{...segmentStyle, ...{height:'100%'}}}>
        Your content
    </Segment>
    

    【讨论】:

    • 只是为了添加到您的最后一个 sn-p,{{...segmentStyle, height:'100%'}} 也可以。
    【解决方案5】:

    Object.assign() 是一个简单的解决方案,但是(当前)top answer 的使用——虽然对于制作无状态组件来说很好,但会导致 OP 合并两个 state 对象的预期目标出现问题。

    使用两个参数,Object.assign() 实际上会就地改变第一个对象,影响未来的实例化。

    例如:

    考虑一个盒子的两种可能的样式配置:

    var styles =  {
      box: {backgroundColor: 'yellow', height: '100px', width: '200px'},
      boxA: {backgroundColor: 'blue'},
    };
    

    所以我们希望我们所有的盒子都具有默认的“盒子”样式,但想用不同的颜色覆盖一些:

    // this will be yellow
    <div style={styles.box}></div>
    
    // this will be blue
    <div style={Object.assign(styles.box, styles.boxA)}></div>
    
    // this SHOULD be yellow, but it's blue.
    <div style={styles.box}></div>
    

    一旦Object.assign() 执行,'styles.box' 对象就会永久更改。

    解决方案是将一个空对象传递给Object.assign()。这样做,您告诉该方法使用您传递的对象生成一个 NEW 对象。像这样:

    // this will be yellow
    <div style={styles.box}></div>
    
    // this will be blue
    <div style={Object.assign({}, styles.box, styles.boxA)}></div>
    
    // a beautiful yellow
    <div style={styles.box}></div>
    

    这种对象就地变异的概念对于 React 至关重要,正确使用 Object.assign() 对于使用像 Redux 这样的库非常有帮助。

    【讨论】:

    • 您关于如何滥用 Object.assign 的示例并不是对(当前)最佳答案中如何使用 Object.assign 的有效表示。
    • 谢谢,进行了编辑以反映(当前)哪个方面是滥用
    • 那里有一段不错的代码。 Object.assign({}, this.state.showStartOverBtn ? {} : this.hidden ,this.btnStyle)} 条件句也很有效
    【解决方案6】:

    Array notaion 是 React Native 中组合样式的最佳方式。

    这显示了如何组合 2 个 Style 对象,

    <Text style={[styles.base, styles.background]} >Test </Text>
    

    这显示了如何组合 Style 对象和属性,

    <Text style={[styles.base, {color: 'red'}]} >Test </Text>
    

    这适用于任何 React Native 应用程序。

    【讨论】:

    • 问题是针对React,而不是React Native
    • React 也可以使用相同的
    • React 从一开始就不支持数组,现在它不再工作了。
    • react 还不支持这样的组合样式。
    • 不明白为什么这个响应有这么多的赞成票。回应题外话,这里我们谈论的是反应,而不是反应原生。 Reactjs 不支持此响应中所说的内容
    【解决方案7】:
        const style1 = {
            backgroundColor: "#2196F3", 
        }
        
        const style2 = {
            color: "white", 
        }
    
        const someComponent = () => {
            return <div style={{ ...style1, ...style2 }}>This has 2 separate styles</div> 
        }
        
    

    注意双花括号。传播运算符是您的朋友。

    【讨论】:

    • 绝对应该被接受为正确答案。救生员!
    • 我同意@RobHern。这应该是公认的答案,它还允许添加其他内联样式,例如: style={{...styles.title, color: backgroundDark ? "#fff" : "#000"}}
    【解决方案8】:

    其实有一个正式的组合方式,如下所示:

    <View style={[style01, style02]} />
    

    但是,有一个小问题,如果其中一个是由父组件传递的,并且它是通过组合形式的方式创建的,我们就有一个大问题:

    // The passing style02 from props: [parentStyle01, parentStyle02]
    
    // Now:
    <View style={[style01, [parentStyle01, parentStyle02]]} />
    

    最后一行会导致 UI 错误,很明显,React Native 无法处理数组中的深层数组。所以我创建了我的辅助函数:

    import { StyleSheet } from 'react-native';
    
    const styleJoiner = (...arg) => StyleSheet.flatten(arg);
    

    通过在任何地方使用我的styleJoiner,您可以组合任何类型的样式并组合样式。即使undefined 或其他无用的类型也不会破坏样式。

    【讨论】:

      【解决方案9】:

      您还可以像这样将类与内联样式结合起来:

      <View style={[className, {paddingTop: 25}]}>
        <Text>Some Text</Text>
      </View>
      

      【讨论】:

      • 不,你不能那样做。这里说的是Reactjs(注意react native),不明白为什么这么赞
      【解决方案10】:

      我发现这对我最有效。它按预期覆盖。

      return <View style={{...styles.local, ...styles.fromProps}} />
      

      【讨论】:

        【解决方案11】:

        需要合并对象中的属性。 例如,

        const boxStyle = {
          width : "50px",
          height : "50px"
        };
        const redBackground = {
          ...boxStyle,
          background: "red",
        };
        const blueBackground = {
          ...boxStyle,
          background: "blue",
        }
        
        
        
        
         <div style={redBackground}></div>
         <div style={blueBackground}></div>
        

        【讨论】:

        • 这绝对是聪明的。
        【解决方案12】:

        对于那些在 React 中寻找这个解决方案的人,如果你想在样式中使用扩展运算符,你应该使用:babel-plugin-transform-object-rest-spread。

        通过 npm 模块安装它并像这样配置你的 .babelrc:

        {
          "presets": ["env", "react"],
          "plugins": ["transform-object-rest-spread"]
        }
        

        那你就可以用like...

        const sizing = { width: 200, height: 200 }
         <div
           className="dragon-avatar-image-background"
           style={{ backgroundColor: blue, ...sizing }}
          />
        

        更多信息:https://babeljs.io/docs/en/babel-plugin-transform-object-rest-spread/

        【讨论】:

          【解决方案13】:

          所以基本上我看错了。据我所知,这不是一个特定于 React 的问题,更多的是一个关于如何将两个 JavaScript 对象组合在一起的 JavaScript 问题(不破坏类似命名的属性)。

          在这个 StackOverflow 答案中,它解释了它。 How can I merge properties of two JavaScript objects dynamically?

          在 jQuery 中,我可以使用 extend 方法。

          【讨论】:

            【解决方案14】:

            为了扩展@PythonIsGreat 所说的内容,我创建了一个全局函数来为我做这件事:

            var css = function(){
                var args = $.merge([true, {}], Array.prototype.splice.call(arguments, 0));
                return $.extend.apply(null, args);
            }
            

            这将对象深度扩展为一个新对象,并允许可变数量的对象作为参数。这允许您执行以下操作:

            return(
            <div style={css(styles.base, styles.first, styles.second,...)} ></div>
            );
            
            var styles = {
              base:{
                //whatever
              },
              first:{
                //whatever
              },
              second:{
                //whatever
              }
            }
            

            【讨论】:

              【解决方案15】:

              为了更进一步,您可以创建一个类似classnames 的辅助函数:

              const styleRules = (...rules) => {
                return rules.filter(Boolean).reduce((result, rule) => {
                  return { ...result, ...rule };
                }, {});
              };
              

              然后在你的组件中有条件地使用它:

              <div style={
              
                styleRules(
                  divStyle,
                  (window.innerWidth >= 768) && divStyleMd,
                  (window.innerWidth < 768) && divStyleSm
                )
              
              }>Hello World!</div>
              

              【讨论】:

                【解决方案16】:

                内联样式的方式:

                <View style={[styles.red, {fontSize: 25}]}>
                  <Text>Hello World</Text>
                </View>
                
                <View style={[styles.red, styles.blue]}>
                  <Text>Hello World</Text>
                </View>
                
                  <View style={{fontSize:10,marginTop:10}}>
                  <Text>Hello World</Text>
                </View>
                

                【讨论】:

                • React 从一开始就不支持数组,现在它不再工作了。
                • 以上评论是正确的,这个答案只适用于 React Native。可以做类似的事情 - 像这样,React 确实支持。
                【解决方案17】:

                如果您想根据条件添加样式,我已经为此构建了一个模块 像这样:

                multipleStyles(styles.icon, { [styles.iconRed]: true })
                

                https://www.npmjs.com/package/react-native-multiple-styles

                【讨论】:

                  【解决方案18】:

                  在 React 中有多种内联样式。

                  <div onClick={eleTemplate} style={{'width': '50%', textAlign: 'center'}}/>
                  

                  【讨论】:

                  • 这是通过什么方式提供多种样式的?
                  • 样式接受花括号内的对象,因此您可以将所有样式作为一个对象并将其分配给一个变量,如下所示。 const combineStyles = {'width': '50%', textAlign: 'center'}
                  猜你喜欢
                  • 2020-02-15
                  • 2018-07-27
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2018-06-29
                  • 2018-09-10
                  • 2018-06-18
                  相关资源
                  最近更新 更多