Javascript 扩展 React.js 组件

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/25720595/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-22 21:44:58  来源:igfitidea点击:

Extending React.js components

javascriptinheritancebackbone.jsreactjs

提问by Ahrengot

One of the things I appreciate the most about Backbone.js is how simple and elegant inheritance works. I'm starting to get to grips with React, and can't really find anything in react that resembles this Backbone code

关于 Backbone.js,我最欣赏的一件事是简单而优雅的继承工作方式。我开始掌握 React,但在 React 中找不到任何类似于此 Backbone 代码的内容

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

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

In react we have mixins, and using those we could get somewhat close to the above example if we went like this

React 中,我们有 mixins,如果我们像这样使用它们,我们可以有点接近上面的例子

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
    }
});

This is less repetitive than defining the same stuff over and over again, but it doesn't seem to be nearly as flexible as the Backbone way. For instance, I get an error if I try to redefine/overwrite a method that exists in one of my mixins. On top of that, the React.js way is more code for me to write.

这比一遍又一遍地定义相同的东西要少,但它似乎不像 Backbone 方式那么灵活。例如,如果我尝试重新定义/覆盖存在于我的一个 mixin 中的方法,我会收到错误消息。最重要的是,React.js 方式是我编写的更多代码。

There is some incredibly clever stuff in react, and it feels like this is more the case of me not getting how to properly do this, than it feels like a feature missing from React.

React 中有一些非常聪明的东西,感觉这更像是我不知道如何正确地做到这一点,而不是感觉像是 React 缺少的一个功能。

Any pointers are greatly appreciated.

任何指针都非常感谢。

采纳答案by Ross Allen

To get something that resembles inheritance (actually compositionas pointed out in comments), you can make an Airplanein your example wrap itself in a Vehicle. If you want to expose methods on Vehiclein the Airplanecomponent, you can use a refand connect them one-by-one. This is not exactly inheritance (it's actually composition), particularly because the this.refs.vehiclewill not be accessible until after the component has been mounted.

要获得类似于继承的东西(实际上是评论中指出的组合),您可以Airplane在示例中将其自身包装在Vehicle. 如果要VehicleAirplane组件中公开方法,可以使用ref并将它们一一连接。这不完全是继承(它实际上是组合),特别是因为在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>
        );
    }
});

Also it's worth mention that in the React official documentationthey prefer composition over inheritance:

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

So What About Inheritance? At Facebook, we use React in thousands of components, and we haven't found any use cases where we would recommend creating component inheritance hierarchies.

Props and composition give you all the flexibility you need to customize a component's look and behavior in an explicit and safe way. Remember that components may accept arbitrary props, including primitive values, React elements, or functions.

If you want to reuse non-UI functionality between components, we suggest extracting it into a separate JavaScript module. The components may import it and use that function, object, or a class, without extending it.

那么继承呢?在 Facebook,我们在数以千计的组件中使用 React,我们还没有发现任何我们建议创建组件继承层次结构的用例。

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

如果您想在组件之间重用非 UI 功能,我们建议将其提取到单独的 JavaScript 模块中。组件可以导入它并使用该函数、对象或类,而无需扩展它。

Another thing worth mention that using ES2015/ES6+ you can also spread the object props from Airplanecomponent to the Vehiclecomponent

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

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

回答by Ashot

If you use webpack+babel+react NPM package set up in your project, then in ES6 OOP implementation it should be as simple as this:

如果你在项目中使用 webpack+babel+react 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'));

Note: Here is a simple starter kit with such set up: https://github.com/alicoding/react-webpack-babel

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

回答by Jim Ma

By leveraging ReactOO, you can easily use inheritance (Disclaimer: I'm the author of ReactOO):

通过利用ReactOO,您可以轻松使用继承(免责声明:我是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>
enter image description here在此处输入图片说明

回答by pgregory

I think extending may be done with using jQuery.extendor similar

我认为扩展可以通过使用jQuery.extend或类似的方式完成

Base.jsx

基础.jsx

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

Child.jsx

儿童.jsx

var Base = require('./Base.jsx');

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