繁体   English   中英

反应依赖注入或类似?

[英]React dependency injection or similar?

在Angular.js中,可以使用依赖注入。 我做了一些浏览,但无法找到它的实现。 React有类似的东西吗?

React有IoC,但没有任何像Angular这样的DI容器的概念。 也就是说,不是让容器知道如何创建对象和传递依赖关系,而是通过在实例化时将props传递给组件来显式传递它们(如<MyComponent items={this.state.items} /> )。

将依赖关系作为道具传递并不是React世界常见的。 道具主要用于将数据传递给组件而不是服务/商店。 但是没有什么可以阻止你将服务/商店甚至组件作为道具传递(当然也没有任何问题)。

React具有context的概念,它是整个组件树的共享对象。 因此,顶级组件可以说其子树的上下文具有包含诸如UserStore,MessageStore等内容的对象。然后,组件层次结构中更下面的组件可以说它想要在其上下文中访问UserStore。 通过这样说,UserStore可以被该组件访问,而不必明确地将其从顶层组件传递到底层,并且请求它的组件不知道它是如何创建/传递给它的。

它具有DI容器的优点,您可以在其中创建对象的中心位置,可以进一步向下传递。 这是一个很好的上下文介绍: https//www.tildedave.com/2014/11/15/introduction-to-contexts-in-react-js.html

上下文仍然是React的一个未记录的功能,这意味着它的API可以在任何即将推出的React版本中进行更改,因此您可能希望稀疏地使用它,直到它被记录下来。

我并不喜欢使用上下文 ,因为它仍然是反应的实验性特征,而且有点笨重。 我也看过像react-di这样的DI框架,但它要求每个组件都要注意DI框架注入依赖关系的方式(即知道依赖关系是在this.props.di对象中)。

如果我们排除上下文,那么在React组件中注入内容的规范方法是使用props。 运行React.createElement时会注入React.createElement ,即每个jsx标记。 React.createElement函数接受一个组件,一些道具和一些子项,并返回一个React元素 (component, props, children) -> element

我创建了一个createComponent函数,它具有与React.createElement几乎相同的签名,但它返回一个组件,即(component, props, children) -> component 这里是:

const createComponent = (type, defaultProps = {}, defaultChildren = null) => {
    return ({ children, ...props }) => {
        return React.createElement(
            type,
            { ...defaultProps, ...props },
            children || defaultChildren
        );
    };
};

返回的组件可以在prop中注入,如下例所示:

const Banner = ({ children, TextComponent }) => {
    return <div className="banner">
        <TextComponent>{children}</TextComponent>
    </div>;
}

const SayHelloComponent = ({ ParagraphComponent }) => {
    return <ParagraphComponent>Hello world!</ParagraphComponent>;
}

const ParentComponent = () => {
    const inject = {
        ParagraphComponent: createComponent(Banner, {
            TextComponent: createComponent('span', {
                className: "my-pretty-class",
            }),
        }),
    }

    return <SayHelloComponent {...inject} />;
}

小提琴: https//jsfiddle.net/8971g8s5/3/

关于这一点的好处是PropTypes仍然可以很好地工作,因此每个组件都可以清楚地声明它想要的属性类型。

此外,注入的接收端不需要依赖任何特殊的实现,只需要React的普通道具系统。 因此,组件无需知道您正在使用依赖注入或如何使用依赖注入,他们只关心他们接收的道具。

反应模式

React组件中依赖注入的大多数解决方案都基于上下文 我认为了解引擎盖下发生的事情是件好事。 在撰写本文时,构建React应用程序的最常用方法之一涉及Redux。 着名的连接函数和Provider使用上下文。

从反应文档

上下文是一种先进的实验性功能。 API可能会在将来的版本中发生变化。

大多数应用程序永远不需要使用上下文。 特别是如果你刚开始使用React,你可能不想使用上下文。 使用上下文会使您的代码更难理解,因为它会使数据流不太清晰。 它类似于使用全局变量通过应用程序传递状态。

如果必须使用上下文,请谨慎使用。

无论您是构建应用程序还是库,都要尝试将上下文的使用隔离到一个小区域,并尽可能避免直接使用上下文API,以便在API更改时更容易升级。

由于使用了IoC容器,我找到了一种在不使用上下文的情况下注入依赖项的方法。

大多数容器支持两种注射:

  • 构造函数注入 :为了使用“构造函数注入”,IoC容器需要能够创建类的实例。 在React中,组件有时只是函数(而不是类),我们不能将组件实例的创建委托给IoC容器。 这意味着由IoC容器驱动的构造函数注入与React不能很好地兼容

  • 属性注入 :如果我们想要的是将依赖项传递给组件而不通过每个组件显式传递它们,那么可以很好地使用React

我使用InversifyJS作为IoC容器,它使用属性注入支持将依赖项传递给组件,而不通过每个组件显式传递它们而不使用上下文:

import { pInject } from "./utils/di";
import { UserStore } from "./store/user";

class User extends React.Component<any, any> {

    @pInject(UserStore)
    private userStore: UserStore; // INJECTED!

    public render() {
        return (
            <h1>{this.userStore.pageTitle}</h1>
        );
    }
}

使用像InversifyJS这样的IoC容器的主要优点是我们没有使用上下文!

你可以在这里了解更多相关信息。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM