【问题标题】:How to implement plugin-based architecture using redux如何使用 redux 实现基于插件的架构
【发布时间】:2019-04-03 16:18:36
【问题描述】:

我正在开发一个网络应用程序,用户可以在其中订阅可用功能,并且所有这些功能都对用户操作产生一定的影响。我正在使用 redux thunk 进行异步操作。

例如。用户可以从产品列表中选择要购买或出售的产品,这会触发一个名为 userIntention 的减速器,然后调用 createProductForm 减速器,它会显示产品形式以及产品信息。用户可以订阅推荐、最优惠等功能,这些功能可以修改产品属性的某些参数,如标签、价格。我想以这样一种方式实现这一点,如果触发 createProductForm,reducer 将动态收集推荐、最佳交易等数据,并根据结果形成用户产品表单。

我们希望让多个开发人员在不与其他人的功能和代码库冲突的情况下开发不同的功能。因此,当开发新功能时,我们没有更改核心逻辑。 但这必须在事先不知道要调用哪些减速器creatingProductForm 的情况下发生,它可能是没有或许多特征减速器。

就像插件,订阅激活一些reducer和中间件。

哪一个最适合这种情况:reducer 或中间件? 我尝试添加动态中间件、动态减速器,但它们都有自己的缺陷。

我尝试过的:

  1. 功能订阅后,名为“ENABLE_FEATURE”的操作被调度到哪些功能缩减程序可以动态侦听注册自己。但我发现很难维护调用哪些减速器。有什么办法可以继续在 redux 商店中列出减速器。
  2. 同样尝试使用中间件,但动态删除其中一个中间件太复杂了。
  3. 在 redux 之外创建自己的实用程序,其中实现了动态 reducer 的注册、订阅,但是由于 dispatch 和 store 不可用,如何从外部 react 组件调用 reducer。

我们正在使用rekit studio 进行开发。

编辑 这是我的应用程序架构。正如你所看到的,所有的特性都是与reducers、store、组件一起独立开发的。 我们需要的是一旦f-core 组件被开发出来,即使我们实现了独立于它的新特性,它也不会受到影响。有点像一个注册表,其中功能可以注册自己,所以f-core 会知道它们的存在。那么这个特性应该已经暴露了一些函数(reducers),这些函数将在运行时决定。 应用架构

/node_modules
package.json
package-lock.json
/public
/src
 - /common
     - configStore.js
     - history.js
     - rootReducer.js
     - routeConfig.js
 - /features
    - /f-core
        - component1.js
         - component1.less
         - index.js
         - route.js
         - /api-service
             - router.js
             - constants.js
             - service.js
         - /redux
             - actions.js
             - constants.js
             - reducer.js
             - initialState.js
             - reducer1.js
     - /f1
         - component1.js
         - component1.less
         - index.js
         - route.js
         - /api-service
             - router.js
             - constants.js
             - service.js
         - /redux
             - actions.js
             - constants.js
             - reducer.js
             - initialState.js
             - reducer1.js
     - /f2
        - component1.js
            - component1.less
         - index.js
         - route.js
         - /api-service
             - router.js
             - constants.js
             - service.js
         - /redux
             - actions.js
             - constants.js
             - reducer.js
             - initialState.js
             - reducer1.js
 - index.js
 - Root.js

【问题讨论】:

  • 鉴于我最了解您的问题,我发布了一个答案。如果我错过/误解了您的问题的详细信息,或者我的解释需要进一步澄清,请告诉我,我很乐意回复。

标签: reactjs redux react-redux redux-thunk


【解决方案1】:

单独开发可插拔 Redux 子状态的一种方法是 1) 编写每个子状态时外部依赖为零,然后 2) 在主应用程序中,使用 Redux-Saga 编排跨越可插拔子状态边界的操作流。

1) 通过仅在其自己的命名空间/目录/插件中引用函数、变量等来编写具有零依赖关系的每个子状态。含义:

  • 所有相关代码的托管,例如化简器、动作类型、动作创建者、选择器、常量、实用程序
  • reducer 仅处理同地操作类型
  • 选择器只能从并置状态拉出

2) 使用 Redux-Saga 来编排跨越子状态边界的动作流。如果来自不同插件的 reducer 需要更新同一事件的状态,请让 saga 监听应用程序/非插件操作,然后分派单独的插件特定操作。

例子:

import { CREATE_ITEM } from '../actions'; // i.e. src/actions
import { moduleA, moduleB } from '../modules';

export function* onCreateItem() {
    yield takeEvery(CREATE_ITEM, function* ({ item }) {
        yield put(moduleA.actionCreators.addNewItem(item));
        yield put(moduleB.actionCreators.setMostRecentlyCreatedItem(item.name));
    })
}

使用这种模式,Redux-Saga 成为应用程序特定操作和应用程序无关子状态之间的间接层,因此每个子状态都可以独立变化。

最后,使用广泛接受的delegation approach 构造选择器,它与上述模式配合得很好。

注意事项:

  • 将会有更多动作和 sagas 需要跟踪
  • 这是我固执己见的方法,我根据使用它扩展 redux 应用程序的经验推荐该方法

【讨论】:

  • 我已经与架构一起编辑了问题。请看一看。谢谢
  • 动态加载减速器不是我见过的方法。难道你不能只存储数据{ fCore: true, f1: true, f2: false },然后使用选择器来确定视图和控制流吗?
  • 我们正在探索fusionjs,它提供了一个更强大的基于插件的架构。我想我应该在评估 fusionjs 之后回到这里。 @bsapaka
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-12-30
  • 2020-02-09
  • 2010-11-09
  • 2011-02-23
  • 1970-01-01
  • 2017-10-19
  • 2018-07-28
相关资源
最近更新 更多