继承和组合中的道具
Props in inheritance and composition
我有一个名为 Panel
的 React class,我想将其用作 UI 中各种特定面板的可重用组件。每个面板都有一个共同的标题栏和一个 "Submit" 按钮,但每种面板的 body 是唯一的。
我可以使用继承 (sub-classing) 或组合来实现此目的,但在这种情况下哪个最好?
我已经尝试 sub-classing,在 parent Panel
中使用渲染方法,然后让 child 面板覆盖 renderBody
方法,render
使用。这似乎崩溃了,因为每个特定的面板都需要自己的道具(例如 "title"),并且当修改后的道具被传递给组件构造函数中的 super
时,React 会抱怨(错误消息是,"When calling super() . . . make sure to pass up the same props that your component's constructor was passed.").由于 "title" 特定于一种面板,我不希望最终消费者必须自己指定 "title" 道具。
class Panel extends React.Component {
render() {
return (
<div>
<div>{this.props.title}</div>
<div>{this.renderBody()}</div>
<div><button>Submit</button></div>
</div>
)
}
}
class SomeSubPanel extends Panel {
constructor(props) {
// React throws the error message at the following line
let newProps = Object.assign({}, props, {title: "Some Sub Panel"})
super(newProps)
}
renderBody() {
return (<div>Panel Body Goes Here</div>)
}
}
使用组合似乎不像 sub-classing 那样整洁,因为每个面板只需要有一个特定的 body,但是 body(即 HTML) 不能在组件之间传递。
拥有 child 可以将特征传递给可重用 parent 组件的组件会是什么 "React way"?
非常感谢!
一定要用构图。一般来说,我认为你不应该扩展你自己的 React 组件。实现方法如下:
class ReusablePanel extends React.Component {
render () {
return (
<div>
<div>{this.props.title}</div>
<button onClick={this.props.onSubmit}>Submit</button>
{this.props.children}
</div>
)
}
}
class FootballPanel extends React.Component {
handleSubmitButtonClick = () => {
// do something
}
render () {
return (
<ReusablePanel title='Football' onSubmit={this.handleSubmitButtonClick}>
<div>{/* Football markup */}</div>
</ReusablePanel>
)
}
}
class ArsenalPanel extends React.Component {
handleSubmitButtonClick = () => {
// do something
}
render () {
return (
<ReusablePanel title='Arsenal' onSubmit={this.handleSubmitButtonClick}>
<div>{/* Arsenal markup */}</div>
</ReusablePanel>
)
}
}
我认为 React 的做法很简单:
// using a function for brevity, but could be a class
let Panel = ({ title, handleSubmit, children }) =>
<div>
<h1>{title}</h1>
{children}
<button onClick={handleSubmit}>Submit</button>
</div>
然后在别处:
<Panel title="Foo" handleSubmit={onSubmit}>{specificChildContent}</Panel>
我有一个名为 Panel
的 React class,我想将其用作 UI 中各种特定面板的可重用组件。每个面板都有一个共同的标题栏和一个 "Submit" 按钮,但每种面板的 body 是唯一的。
我可以使用继承 (sub-classing) 或组合来实现此目的,但在这种情况下哪个最好?
我已经尝试 sub-classing,在 parent Panel
中使用渲染方法,然后让 child 面板覆盖 renderBody
方法,render
使用。这似乎崩溃了,因为每个特定的面板都需要自己的道具(例如 "title"),并且当修改后的道具被传递给组件构造函数中的 super
时,React 会抱怨(错误消息是,"When calling super() . . . make sure to pass up the same props that your component's constructor was passed.").由于 "title" 特定于一种面板,我不希望最终消费者必须自己指定 "title" 道具。
class Panel extends React.Component {
render() {
return (
<div>
<div>{this.props.title}</div>
<div>{this.renderBody()}</div>
<div><button>Submit</button></div>
</div>
)
}
}
class SomeSubPanel extends Panel {
constructor(props) {
// React throws the error message at the following line
let newProps = Object.assign({}, props, {title: "Some Sub Panel"})
super(newProps)
}
renderBody() {
return (<div>Panel Body Goes Here</div>)
}
}
使用组合似乎不像 sub-classing 那样整洁,因为每个面板只需要有一个特定的 body,但是 body(即 HTML) 不能在组件之间传递。
拥有 child 可以将特征传递给可重用 parent 组件的组件会是什么 "React way"?
非常感谢!
一定要用构图。一般来说,我认为你不应该扩展你自己的 React 组件。实现方法如下:
class ReusablePanel extends React.Component {
render () {
return (
<div>
<div>{this.props.title}</div>
<button onClick={this.props.onSubmit}>Submit</button>
{this.props.children}
</div>
)
}
}
class FootballPanel extends React.Component {
handleSubmitButtonClick = () => {
// do something
}
render () {
return (
<ReusablePanel title='Football' onSubmit={this.handleSubmitButtonClick}>
<div>{/* Football markup */}</div>
</ReusablePanel>
)
}
}
class ArsenalPanel extends React.Component {
handleSubmitButtonClick = () => {
// do something
}
render () {
return (
<ReusablePanel title='Arsenal' onSubmit={this.handleSubmitButtonClick}>
<div>{/* Arsenal markup */}</div>
</ReusablePanel>
)
}
}
我认为 React 的做法很简单:
// using a function for brevity, but could be a class
let Panel = ({ title, handleSubmit, children }) =>
<div>
<h1>{title}</h1>
{children}
<button onClick={handleSubmit}>Submit</button>
</div>
然后在别处:
<Panel title="Foo" handleSubmit={onSubmit}>{specificChildContent}</Panel>