扩展React.js组件

我最欣赏Backbone.js的一件事就是简单而优雅的inheritance是如何工作的。 我开始熟悉React,并且不能真正find类似于这个Backbone代码的反应

var Vehicle = Backbone.View.extend({ methodA: function() { // ... } methodB: function() { // ... } methodC: function() { // ... } }); var Airplane = Vehicle.extend({ methodC: function() { // Overwrite methodC from super } }); 

在反应中,我们有mixin ,如果我们这样做的话,使用那些我们可能会接近上面的例子

 var vehicleMethods = { methodA: function() { // ... } methodB: function() { // ... } } var Vehicle = React.createClass({ mixins: [vehicleMethods] methodC: function() { // Define method C for vehicle } }); var Airplane = React.createClass({ mixins: [vehicleMethods] methodC: function() { // Define method C again for airplane } }); 

这比重复定义相同的东西的重复性要less,但似乎并没有像骨干那样灵活。 例如,如果我尝试重新定义/覆盖我的某个mixin中存在的方法,则会出现错误。 最重要的是,React.js的方式是我编写的代码。

在反应中有一些令人难以置信的聪明的东西,感觉就像更多的情况下,我没有得到如何正确地做到这一点,比感觉像一个从React中缺less的function。

任何指针,不胜感激。

为了得到类似于inheritance的东西(实际上就像注释中指出的那样),你可以让你的例子中的Airplane将自己包装在一辆Vehicle 。 如果你想在Airplane组件上展示Vehicle方法,你可以使用一个ref并且一个一个地连接它们。 这不完全是inheritance(它实际上是组合 ),特别是因为this.refs.vehicle将不可访问,直到该组件已被挂载。

 var Vehicle = React.createClass({ ... }); var Airplane = React.createClass({ methodA: function() { if (this.refs != null) return this.refs.vehicle.methodA(); }, ... render: function() { return ( <Vehicle ref="vehicle"> <h1>J/K I'm an airplane</h1> </Vehicle> ); } }); 

另外值得一提的是,在React官方文档中,他们更喜欢组合的inheritance:

那么inheritance呢? 在Facebook上,我们在成千上万的组件中使用了React,而且我们还没有发现任何build议创build组件inheritance层次结构的用例。

道具和构图为您提供了所有需要的灵活性,以明确和安全的方式自定义组件的外观和行为。 请记住,组件可以接受任意道具,包括原始值,React元素或函数。

如果你想在组件之间重用非UIfunction,我们build议把它解压到一个单独的JavaScript模块中。 组件可以将其导入并使用该函数,对象或类,而不对其进行扩展。

另外值得一提的是,使用ES2015 / ES6 +还可以将对象道具从Airplane组件传播到Vehicle组件

 render: function() { return ( <Vehicle {...this.props}> <h1>J/K I'm an airplane</h1> </Vehicle> ); } 

如果您使用webpack + babel +在您的项目中设置了NPM包,那么在ES6 OOP实现中应该如此简单:

 import React, { Component } from 'react'; import ReactDOM from 'react-dom'; class BaseComponentClass extends Component { componentDidMount() {} render() { return (<div>Base Component</div>) } } class InheritedComponentClass extends BaseComponentClass { // componentDidMount is inherited render() { return (<div>Inherited Component</div>) } // render is overridden } ReactDOM.render(<InheritedComponentClass></InheritedComponentClass>, document.getElementById('InheritedComponentClassHolder')); 

注意:这是一个简单的入门套件,具有这样的设置: https : //github.com/alicoding/react-webpack-babel

通过利用ReactOO ,您可以轻松使用inheritance( 免责声明 :我是ReactOO的作者):

 (function () { // Class definitions. ReactOO requires class definition first just like you did in an OO way. window.Vehicle = window.ReactOO.ReactBase.extend({ getReactDisplayName: function () { return 'Vehicle'; }, onReactRender: function (reactInstance) { var self = this; var text = self.methodC(); return React.createElement('div', {}, text); }, methodA: function () { console.log('Vehicle method A'); }, methodB: function () { console.log('Vehicle method B'); }, methodC: function () { return 'Vehicle method C'; } }); window.Airplane = window.Vehicle.extend({ getReactDisplayName: function () { return 'Airplane'; }, methodC: function () { // Call this._super() to execute parent method. //this._super(); return 'Airplane method C'; } }); var vehicle = new window.Vehicle(); vehicle.render({}, '#vehicle'); var airPlane = new window.Airplane(); airPlane.render({}, '#airPlane'); })(); 
 <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>ReactOO Vehicle-Aireplane Example</title> <link rel="stylesheet" href="css/base.css" /> <script src="scripts/react.js"></script> <script src="scripts/react-dom.js"></script> <script src="../src/reactoo.js"></script> </head> <body> <div id="vehicle"> </div> <div id="airPlane"> </div> <script src="scripts/vehicleAirplane.js"> </script> </body> </html> 

我想扩展可能会使用jQuery.extend或类似的

Base.jsx

 module.exports = { methodA:function(){ ... } } 

Child.jsx

 var Base = require('./Base.jsx'); module.exports = React.createClass($.extend({},Base,{ methodB:function(){ ... this.methodA(); ... }, render:function(){ return ... } }));