2017-06-16 26 views
3

如果o对象包含一个密钥/值对:foo: 'bar'可以我取决于这些结果?:JSX中道具的排序是否重要?

// foo will be 'bar' 
<MyComponent 
    foo='should not override' 
    {...o} 
    /> 

// foo will be 'overridden' 
<MyComponent 
    {...o} 
    foo='overridden' 
    /> 

换句话说,是属性的排序,同时使用spread操作者显著?

回答

3

是的。它的工作原理完全按照您的例子说

您例如被翻译成:

// foo will be 'bar' 
<MyComponent 
    {/* ...other 'o' keys/values...*/} 
    foo='should not override' 
    {/* ...other 'o' keys/values...*/} 
    foo='bar' 
/> 

// foo will be 'overridden' 
<MyComponent 
    foo='bar' 
    {/* ...other 'o' keys/values...*/} 
    foo='overridden' 
    {/* ...other 'o' keys/values...*/} 
/> 

也因此,它总是覆盖的最后一个

1

看看这个沙盒证明:

https://codesandbox.io/s/Q1GMx9KM9

正如你所看到的,它的行为与你在问题中的理论完全相同。

编辑 SO段:

class MyComponent extends React.Component { 
 
    render() { 
 
    return <div>{this.props.foo}</div> 
 
    } 
 
} 
 

 
const styles = { 
 
    fontFamily: 'sans-serif', 
 
    textAlign: 'center', 
 
}; 
 

 
const o = { foo: 'bar' }; 
 

 
const App =() => 
 
    <div style={styles}> 
 
    <h2>Spreading after explicit property</h2> 
 
    <MyComponent foo="will be overriden" {...o} /> 
 
    <h2>Spreading before explicit property</h2> 
 
    <MyComponent {...o} foo="was overriden" /> 
 
    </div>; 
 

 
ReactDOM.render(<App />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script> 
 
<div id="root"></div>

1

是,排序很重要。确切的原因是巴贝尔如何处理JSX。您可以在Babel REPL看到:

<MyComponent foo="should not override" {...o}> 

</MyComponent> 

变为:

React.createElement(MyComponent, _extends({ foo: "overridden" }, o)); 

哪里_extends只是Object.assign,或者如果浏览器不支持它,_extends在功能上是相同的。根据MDN文档:

如果目标对象中的属性具有相同的键,则它们将被源中的属性覆盖。后来的资源属性会覆盖前面的属性。

(强调是我的)。因此,使用Object.assign将道具传递给组件时,目标是{ foo: "overridden" },而源是o。由于目标和源中都存在foo,因此目标中的foo将被覆盖。这也适用于:

<MyComponent {...o} foo="overridden"> 

</MyComponent> 

这里,JSX是transpiled到对面:

React.createElement(MyComponent, _extends({}, o, { foo: "overriden" })); 

这是一个有点不同,因为在这里,目标是一个空的对象,但报价的后半段来自MDN适用。这里的来源是o{ foo: "overridden" }。由于foo存在于两个来源中,因此{ foo: "overridden" }中的foo将从o覆盖foo