难以理解 JSX 传播运算符
Trouble understanding JSX spread operator
给出来自 React 文档的示例代码:
var props = {};
props.foo = x;
props.bar = y;
var component = <Component {...props} />;
我调查了 ...props
实际计算的结果,即:
React.__spread({}, props)
这又计算为 {foo: x, bar: y}
。
但我想知道的是,为什么我不能这样做:
var component = <Component props />;
我没明白展开运算符的意义所在。
这有助于使您的代码更加简洁 - 由于 props
是一个对象,展开运算符采用您传入的对象的 属性 并将它们应用于零件。因此,该组件将具有属性 foo
,值为 x
和 bar
,值为 y
.
这将是相同的:
var component = <Component foo={props.foo} bar={props.bar} />;
更短
关于 object-rest-spread 语法如何与 React 协同工作的最佳概述之一发表于 reactpatterns.com:
JSX spread attributes
Spread Attributes is a JSX feature. It's syntactic sugar for passing all of an object's properties as JSX attributes.
These two examples are equivalent.
// props written as attributes
<main className="main" role="main">{children}</main>
// props "spread" from object
<main {...{className: "main", role: "main", children}} />
Use this to forward props
to underlying components.
const FancyDiv = props =>
<div className="fancy" {...props} />
Now, I can expect FancyDiv
to add the attributes it's concerned with as well as those it's not.
<FancyDiv data-id="my-fancy-div">So Fancy</FancyDiv>
// output: <div className="fancy" data-id="my-fancy-div">So Fancy</div>
Keep in mind that order matters. If props.className
is defined, it'll clobber the className
defined by FancyDiv
<FancyDiv className="my-fancy-div" />
// output: <div className="my-fancy-div"></div>
We can make FancyDiv
s className always "win" by placing it after the spread props ({...props})
.
// my `className` clobbers your `className`
const FancyDiv = props =>
<div {...props} className="fancy" />
You should handle these types of props gracefully. In this case, I'll merge the author's props.className
with the className
needed to style my component.
const FancyDiv = ({ className, ...props }) =>
<div
className={["fancy", className].join(' ')}
{...props}
/>
-- 引自reactpatterns.com by @chantastic
Steven Luscher 在 babeljs 博客 post React on ES6+ 上发表了另一个很好的概述:
Destructuring & spread attributes
Often when composing components, we might want to pass down most of a parent component’s props to a child component, but not all of them. In combining ES6+ destructuring with JSX spread attributes, this becomes possible without ceremony:
class AutoloadingPostsGrid extends React.Component {
render() {
const {
className,
...others // contains all properties of this.props except for className
} = this.props;
return (
<div className={className}>
<PostsGrid {...others} />
<button onClick={this.handleLoadMoreClick}>Load more</button>
</div>
);
}
}
-- 引用自 "BabelJS.org blog - React on ES6+" by Steven Luscher
给出来自 React 文档的示例代码:
var props = {};
props.foo = x;
props.bar = y;
var component = <Component {...props} />;
我调查了 ...props
实际计算的结果,即:
React.__spread({}, props)
这又计算为 {foo: x, bar: y}
。
但我想知道的是,为什么我不能这样做:
var component = <Component props />;
我没明白展开运算符的意义所在。
这有助于使您的代码更加简洁 - 由于 props
是一个对象,展开运算符采用您传入的对象的 属性 并将它们应用于零件。因此,该组件将具有属性 foo
,值为 x
和 bar
,值为 y
.
这将是相同的:
var component = <Component foo={props.foo} bar={props.bar} />;
更短
关于 object-rest-spread 语法如何与 React 协同工作的最佳概述之一发表于 reactpatterns.com:
JSX spread attributes
Spread Attributes is a JSX feature. It's syntactic sugar for passing all of an object's properties as JSX attributes.
These two examples are equivalent.
// props written as attributes <main className="main" role="main">{children}</main> // props "spread" from object <main {...{className: "main", role: "main", children}} />
Use this to forward
props
to underlying components.const FancyDiv = props => <div className="fancy" {...props} />
Now, I can expect
FancyDiv
to add the attributes it's concerned with as well as those it's not.<FancyDiv data-id="my-fancy-div">So Fancy</FancyDiv> // output: <div className="fancy" data-id="my-fancy-div">So Fancy</div>
Keep in mind that order matters. If
props.className
is defined, it'll clobber theclassName
defined byFancyDiv
<FancyDiv className="my-fancy-div" /> // output: <div className="my-fancy-div"></div>
We can make
FancyDiv
s className always "win" by placing it after the spread props({...props})
.// my `className` clobbers your `className` const FancyDiv = props => <div {...props} className="fancy" />
You should handle these types of props gracefully. In this case, I'll merge the author's
props.className
with theclassName
needed to style my component.const FancyDiv = ({ className, ...props }) => <div className={["fancy", className].join(' ')} {...props} />
-- 引自reactpatterns.com by @chantastic
Steven Luscher 在 babeljs 博客 post React on ES6+ 上发表了另一个很好的概述:
Destructuring & spread attributes
Often when composing components, we might want to pass down most of a parent component’s props to a child component, but not all of them. In combining ES6+ destructuring with JSX spread attributes, this becomes possible without ceremony:
class AutoloadingPostsGrid extends React.Component { render() { const { className, ...others // contains all properties of this.props except for className } = this.props; return ( <div className={className}> <PostsGrid {...others} /> <button onClick={this.handleLoadMoreClick}>Load more</button> </div> ); } }
-- 引用自 "BabelJS.org blog - React on ES6+" by Steven Luscher