继承 React 组件的正确方式
Correct way to inherit React components
我知道我的问题有点偏,但是我在Javascript和prototypes
很新,我也看了,但是我不太明白如何申请那个技术对我的实际问题。所以一个例子会很有帮助。
所以我有一个 React
组件,基本上看起来像这样:
var Component1 = React.createClass({
getInitialState: function () {
return ({
searchable: true,
})
},
function1: function () {
return ({
somevalue
})
},
render: function () {
var redText = {
color: 'red'
};
var redBorder = {
color: 'red',
border: '1px solid red'
};
return (
<form>
<div>
<a onClick={this.props.handleAddClick}>Something</a>
</div>
<div>
<label>Some label</label>
<input type="text"/>
</div>
</form> )
});
我也有 Component2
,它基本上完全相同,但在其 render
函数的 return
中多了一个 <input/>
。
我也有Component3
,功能相同,但render()
功能不同。
那么这里如何应用继承,避免复制粘贴3次呢?我只是错过了一些实际的插图,所以我很感激。
Edit1____________________________________________________
所以我尝试按照第一个答案实现 Prototype 继承,但 React 似乎没有看到这些功能:getInitialState()
为 null,渲染后初始状态为 null。这种方法有什么问题?
我也试着按照课本去做了:
function MyPrototype() {};
MyPrototype.prototype.getInitialState = function () {
return ({
someProperty: true;
})
};
function Component1() {};
Component1.prototype = Object.create(MyPrototype.prototype);
Component1.prototype.render = function () {
console.log(this);
return (<div></div>)};
var MyComponent1 = React.createClass(new Component1());
但是当我打开浏览器时,出现错误:Uncaught Invariant Violation: createClass(...): Class specification must implement a
rendermethod.
我这样做错了什么?
Edit2_______________________________________________
实际上,我看到 React 既不支持混合也不支持原型。应该改用合成。它在这篇文章中解释:
Dan Abramov's article Mixins Are Dead. Long Live Composition
在 React 中,组件的继承是非常不鼓励的。
React 更适合通过组合来表达相同的关系。
下面是一个使用合成的例子:
class Button extends Component {
render() {
return (
<div className='Button' style={{ color: this.props.color }}>
{this.props.children}
</div>
)
}
}
class DeleteButton extends Component {
render() {
return (
<Button color='red'>Delete</Button>
)
}
}
请注意 DeleteButton
如何使用 Button
的外观而不继承 。相反,Button
通过 props
定义其可配置部分,并且 DeleteButton
提供这些道具。在实际的 DOM 中,<Button />
和 <DeleteButton />
都会渲染到单个 DOM 节点——递归解析发生在 render()
时间,这就是React 的核心思想。
事实上,如果您不需要生命周期钩子或本地状态,您甚至可以将组件定义为函数:
function Button({ color, children }) {
return (
<div className='Button' style={{ color }}>
{children}
</div>
)
}
function DeleteButton() {
return (
<Button color='red'>Delete</Button>
)
}
您甚至可以将 类 与函数混合使用。这对于继承来说是不可能的,但对于组合来说效果很好。
至于您的具体用例:
I also have Component2
which is basically absolutely the same, but has one additional <input/>
inside the return of its render function.
您可以让 Component1
接受 this.props.children
并在 render()
方法的 return 值中使用它们,并让 Component2
渲染到 <Component1><input /></Component>
。这与我上面展示的非常相似。你也不必使用 children
属性——你可以在任何属性中传递一个 React 元素,例如<Component1 footer={<input />} />
,然后就可以在Component1
.
里面使用this.props.footer
I also have Component3
, which shares same functions, but has different render() function.
如果他们共享任何其他代码(例如计算某些数据的实用程序),请将该代码从组件外部移到共享模块中,然后从两个组件导入它。
如果他们共享任何 UI,请将其提取到另一个组件中,然后从您的两个组件中使用它。
我知道我的问题有点偏,但是我在Javascript和prototypes
很新,我也看了,但是我不太明白如何申请那个技术对我的实际问题。所以一个例子会很有帮助。
所以我有一个 React
组件,基本上看起来像这样:
var Component1 = React.createClass({
getInitialState: function () {
return ({
searchable: true,
})
},
function1: function () {
return ({
somevalue
})
},
render: function () {
var redText = {
color: 'red'
};
var redBorder = {
color: 'red',
border: '1px solid red'
};
return (
<form>
<div>
<a onClick={this.props.handleAddClick}>Something</a>
</div>
<div>
<label>Some label</label>
<input type="text"/>
</div>
</form> )
});
我也有 Component2
,它基本上完全相同,但在其 render
函数的 return
中多了一个 <input/>
。
我也有Component3
,功能相同,但render()
功能不同。
那么这里如何应用继承,避免复制粘贴3次呢?我只是错过了一些实际的插图,所以我很感激。
Edit1____________________________________________________
所以我尝试按照第一个答案实现 Prototype 继承,但 React 似乎没有看到这些功能:getInitialState()
为 null,渲染后初始状态为 null。这种方法有什么问题?
我也试着按照课本去做了:
function MyPrototype() {};
MyPrototype.prototype.getInitialState = function () {
return ({
someProperty: true;
})
};
function Component1() {};
Component1.prototype = Object.create(MyPrototype.prototype);
Component1.prototype.render = function () {
console.log(this);
return (<div></div>)};
var MyComponent1 = React.createClass(new Component1());
但是当我打开浏览器时,出现错误:Uncaught Invariant Violation: createClass(...): Class specification must implement a
rendermethod.
我这样做错了什么?
Edit2_______________________________________________
实际上,我看到 React 既不支持混合也不支持原型。应该改用合成。它在这篇文章中解释: Dan Abramov's article Mixins Are Dead. Long Live Composition
在 React 中,组件的继承是非常不鼓励的。
React 更适合通过组合来表达相同的关系。
下面是一个使用合成的例子:
class Button extends Component {
render() {
return (
<div className='Button' style={{ color: this.props.color }}>
{this.props.children}
</div>
)
}
}
class DeleteButton extends Component {
render() {
return (
<Button color='red'>Delete</Button>
)
}
}
请注意 DeleteButton
如何使用 Button
的外观而不继承 。相反,Button
通过 props
定义其可配置部分,并且 DeleteButton
提供这些道具。在实际的 DOM 中,<Button />
和 <DeleteButton />
都会渲染到单个 DOM 节点——递归解析发生在 render()
时间,这就是React 的核心思想。
事实上,如果您不需要生命周期钩子或本地状态,您甚至可以将组件定义为函数:
function Button({ color, children }) {
return (
<div className='Button' style={{ color }}>
{children}
</div>
)
}
function DeleteButton() {
return (
<Button color='red'>Delete</Button>
)
}
您甚至可以将 类 与函数混合使用。这对于继承来说是不可能的,但对于组合来说效果很好。
至于您的具体用例:
I also have
Component2
which is basically absolutely the same, but has one additional<input/>
inside the return of its render function.
您可以让 Component1
接受 this.props.children
并在 render()
方法的 return 值中使用它们,并让 Component2
渲染到 <Component1><input /></Component>
。这与我上面展示的非常相似。你也不必使用 children
属性——你可以在任何属性中传递一个 React 元素,例如<Component1 footer={<input />} />
,然后就可以在Component1
.
this.props.footer
I also have
Component3
, which shares same functions, but has different render() function.
如果他们共享任何其他代码(例如计算某些数据的实用程序),请将该代码从组件外部移到共享模块中,然后从两个组件导入它。
如果他们共享任何 UI,请将其提取到另一个组件中,然后从您的两个组件中使用它。