react ES6 的 mixin 替代品

IT技术 reactjs ecmascript-6
2021-05-16 18:23:34

在使用 ES6 类时,我正在寻找 React mixin 的替代方案。

我想在我的 React 组件中注入一些函数,但这些函数需要 React 元素。

React ES5 为此使用了 mixins,但 React Classes 不支持 mixins。React 类中 mixin 的替代方法是什么?

4个回答

混入在未来的阵营将不被支持您应该使用高阶组件来代替它们。这个要点为这个概念提供了很好的解释。

与其将额外的功能混合到您的组件中,您还应该创建一个单独的功能,以便为其他组件提供此功能。

class MyComponent extends React.component {
    render() {
        //...
    }
}

export default extraFunctionality(MyComponent);

如果你使用带有 ES7 插件的 Babel,你可以使用装饰器语法:

@extraFunctionality
class MyComponent extends React.component {
    render() {
        //...
    }
}

请记住,MyComponent,一个 JS 类,只是语法糖,因为在幕后将用作函数构造函数,因此请记住,一个简单的技巧将是这样的:

var MyMixin = require('whatever/path');
class MyComponent extends React.Component{
    constructor(props){
        super(props);
        MyMixin.call(this); //this line adds the methods
        this.state = {message: 'Hello world'};
    }
    render(){
        return (
            <div>{this.state.message}</div>
        );
    }
}

然后你的 Mixin module必须用你的 mixin 函数导出一个函数

module.exports = function(){
    var self = this;
    this.method1 = function(){
        // do stuff
        self.setState({
            message: "hello again"
        });
    }
    this.method2 = function(){
        // do more stuff
    }
}

您可以使用匿名函数在类周围包装一个或多个类React.Component以添加额外的功能:

首先创建具有附加功能的包装类:

compExtras.jsx

export default superClass => class extends superClass {

  constructor(props) {  // take props from 'MyComp'.
    super(props);
    this.foo = 'some value';
    this.someChildProp = props.bar; // You can use props of 'MyComp'.
  }

  someExtraMethod(x) {
    return [x, this.foo, this.childProp];
  }
};

现在创建一个普通的组件,React.Component用你的extras-class扩展以注入额外的功能:

myComp.jsx

import extras from './compExtras.js';

class MyComp extends extras(React.Component) {  // extend 'React.Component' with 'extras'

  constructor(props) {
    super(props);  // Pass props to the 'extras' class.
    this.qux = 'some value';
  }

  render() {
    console.log(this.someExtraMethod('foo'));  // You have access to that method.
    return <div></div>;
  }
}

如果您想为一个组件使用多个扩展,请像这样创建您的组件:

class MyComp extends extrasOne(extrasTwo(React.Component)) {

只要确保每个extras-class传递props给它的父类super(props),这样每个类都可以访问props.

这对我有用,可能会有更多的安全保护,但概念就在那里。优点是您可以从原始组件访问 mixin 提供的功能,这是使用装饰器或高阶组件无法实现的:

var MixinComposer = (ComposedComponent, Mixin) => class extends React.Component {
    constructor(props) {
        super(props);
        Object.getOwnPropertyNames(Mixin.prototype).forEach((func) => {
            if (func != 'constructor')
            ComposedComponent.prototype[func] = Mixin.prototype[func]
        })
        this.composed = <ComposedComponent {...this.props} {...this.state}/>
    }
    render() {
        return this.composed;
    }
}

const FooMixin = class {
    foo() { return "foo" }
}

const MyComponent = MixinComposer(class extends React.Component {
    render() {
        return (<div>{ this.foo() }</div>)
    }
}, FooMixin)