mobx redux_Redux vs MobX:哪个最适合您的项目?

mobx redux

对于许多JavaScript开发人员而言,Redux的最大抱怨是实现功能所需的样板代码数量。 更好的替代方法是MobX,它提供类似的功能,但编写的代码较少。

对于MobX的新手,请快速浏览一下MobX的创建者编写的介绍 。 您也可以通过本教程来获得一些实践经验。

本文的目的是帮助JavaScript开发人员确定这两种状态管理解决方案中的哪一种最适合其项目。 我已将此CRUD Redux项目迁移到MobX,以用作本文的示例。 我将首先讨论使用MobX的利弊,然后我将演示两种版本的实际代码示例,以说明两者之间的区别。

可以在GitHub上找到本文提到的项目的代码:

如果您喜欢这篇文章,那么您可能还想注册SitePoint Premium,并观看我们使用React和Redux处理表单的课程。

数据形状像鸟,将Redux迁移到MobX

Redux和MobX有什么共同点?

首先,让我们看一下两者的共同点。 他们:

  • 是开源库
  • 提供客户端状态管理
  • 通过redux-devtools-extension支持时间旅行调试
  • 不受特定框架约束
  • 对React / React Native框架有广泛的支持。

使用MobX的4个理由

现在,让我们看一下Redux和MobX之间的主要区别。

1.易于学习和使用

对于初学者,您可以在30分钟内学习如何使用MobX。 一旦学习了基础知识,就是这样。 您无需学习任何新知识。 使用Redux,基础也很容易。 但是,一旦开始构建更复杂的应用程序,就必须处理:

使用MobX,可以“神奇地”处理所有这些情况。 您不需要其他库来处理这种情况。

2.减少编写代码

要在Redux中实现功能,您至少需要更新四个工件。 这包括编写用于化简器,操作,容器和组件的代码。 如果您正在做一个小型项目,这会特别烦人。 MobX仅要求您至少更新两个工件(即商店和视图组件)。

3.全面支持面向对象的编程

如果您喜欢编写面向对象的代码,将很高兴知道您可以使用OOP通过MobX来实现状态管理逻辑。 通过使用@observable@observer之类的装饰器,您可以轻松地使普通JavaScript组件和存储具有响应性。 如果您更喜欢函数式编程,那没问题-也支持。 另一方面,Redux在很大程度上致力于功能编程原则。 但是,如果需要基于类的方法,则可以使用redux-connect-decorator库。

4.处理嵌套数据很容易

在大多数JavaScript应用程序中,您会发现自己正在处理关系数据或嵌套数据。 为了能够在Redux存储中使用它,您必须首先对其进行规范化 。 接下来,您必须编写更多代码来管理对规范化数据中引用的跟踪。

在MobX中, 建议以非规范化形式存储数据。 MobX可以为您跟踪关系,并将自动重新呈现更改。 通过使用域对象存储数据,您可以直接引用其他存储中定义的其他域对象。 另外,您可以对观察值使用(@)计算的修饰符修饰符,以轻松解决复杂的数据挑战。

不使用MobX的3个理由

1.太多的自由

Redux是一个框架,提供了有关如何编写状态代码的严格准则。 这意味着您可以轻松编写测试并开发可维护的代码。 MobX是一个库,没有关于如何实现它的规则。 这样做的危险在于,采用快捷方式并应用快速修复程序非常容易,这可能导致无法维护的代码。

2.难以调试

MobX的内部代码“神奇地”处理了许多逻辑,使您的应用程序具有响应性。 在存储区和组件之间有一个不可见的区域,您的数据在其中传递,这使您在遇到问题时难以调试。 如果直接在组件中更改状态,而不使用@actions ,那么将很难确定错误的来源。

3.可能有更好的替代MobX

在软件开发中,不断出现新的趋势。 在短短几年内,当前的软件技术会Swift失去动力。 目前,有几种解决方案与Redux和Mobx竞争。 有几个例子是继电器/阿波罗和GraphQLAlt.js连衣 。 这些技术中的任何一种都有可能成为最受欢迎的技术。 如果您真的想知道哪一个最适合您,则必须全部尝试。

代码比较:Redux vs MobX

理论足够多,让我们看一下代码。 首先,我们比较每个版本的引导方式。

自举

Redux版本:
在Redux中,我们首先定义商店,然后通过Provider将其传递给App 。 我们还需要定义redux-thunkredux-promise-middleware来处理异步功能。 redux-devtools-extension允许我们在时间旅行模式下调试商店。

// src/store.js
import { applyMiddleware, createStore } from "redux";
import thunk from "redux-thunk";
import promise from "redux-promise-middleware";
import { composeWithDevTools } from 'redux-devtools-extension';
import rootReducer from "./reducers";

const middleware = composeWithDevTools(applyMiddleware(promise(), thunk));

export default createStore(rootReducer, middleware);

-------------------------------------------------------------------------------

// src/index.js
…
ReactDOM.render(
  <BrowserRouter>
    <Provider store={store}>
      <App />
    </Provider>
  </BrowserRouter>,
  document.getElementById('root')
);

免费学习PHP!

全面介绍PHP和MySQL,从而实现服务器端编程的飞跃。

原价$ 11.95 您的完全免费

MobX版本:
在MobX中,我们需要设置多个商店。 在这种情况下,我仅使用一个商店,将其放置在名为allStores的集合中。 然后使用Provider将商店集合传递给App

如前所述,MobX不需要外部库来处理异步操作,因此行数更少。 但是,我们确实需要mobx-remotedev连接到redux-devtools-extension调试工具。

// src/stores/index.js
import remotedev from 'mobx-remotedev';
import Store from './store';

const contactConfig = {
  name:'Contact Store',
  global: true,
  onlyActions:true,
  filters: {
    whitelist: /fetch|update|create|Event|entity|entities|handleErrors/
  }
};

const contactStore = new Store('api/contacts');

const allStores = {
  contactStore: remotedev(contactStore, contactConfig)
};

export default allStores;

-------------------------------------------------------------------------------

// src/index.js
…
ReactDOM.render(
  <BrowserRouter>
    <Provider stores={allStores}>
      <App />
    </Provider>
  </BrowserRouter>,
  document.getElementById('root')
);

这两个版本中的代码量大致相同。 MobX的导入语句较少。

道具注射

Redux版本:
在Redux中,使用react-redux的connect()函数connect()状态和动作传递给prop。

// src/pages/contact-form-page.js
…
  // accessing props
  <ContactForm
    contact={this.props.contact}
    loading={this.props.loading}
    onSubmit={this.submit}
  />
…

// function for injecting state into props
function mapStateToProps(state) {
  return {
    contact: state.contactStore.contact,
    errors: state.contactStore.errors
  }
}

// injecting both state and actions into props
export default connect(mapStateToProps, { newContact,
  saveContact,
  fetchContact,
  updateContact
})(ContactFormPage);

MobX版本:
在MobX中,我们只需注入stores集合。 我们在容器或组件类的顶部使用@inject来执行此操作。 这使得stores可以在props ,从而使我们能够访问特定商店,并将其传递给子组件。 状态和动作都可以通过store对象中的属性访问,因此不需要像Redux一样单独传递它们。

// src/pages/contact-form-page.js

…
@inject("stores") @observer // injecting store into props
class ContactFormPage extends Component {
…
  // accessing store via props
  const { contactStore:store } = this.props.stores;
  return (
      <ContactForm
        store={store}
        form={this.form}
        contact={store.entity}
      />
  )
…
}

MobX版本似乎更易于阅读。 但是,我们可以使用redux-connect-decorators简化Redux代码。 在这种情况下,不会有明确的赢家。

定义商店,动作和减少者

为了使本文简洁,我将向您展示一个动作的代码示例。

Redux版本:
在Redux中,我们需要定义操作和减少器。

// src/actions/contact-actions.js
…
export function fetchContacts(){
  return dispatch => {
    dispatch({
      type: 'FETCH_CONTACTS',
      payload: client.get(url)
    })
  }
}
…

// src/reducers/contact-reducer
…
switch (action.type) {
    case 'FETCH_CONTACTS_FULFILLED': {
      return {
        ...state,
        contacts: action.payload.data.data || action.payload.data,
        loading: false,
        errors: {}
      }
    }

    case 'FETCH_CONTACTS_PENDING': {
      return {
        ...state,
        loading: true,
        errors: {}
      }
    }

    case 'FETCH_CONTACTS_REJECTED': {
      return {
        ...state,
        loading: false,
        errors: { global: action.payload.message }
      }
    }
}
…

MobX版本:
在MobX中,动作和减速器的逻辑是在一类中完成的。 我定义了一个异步动作,该动作调用在收到responseentities fetched另一个动作entities fetched

由于MobX使用OOP样式,因此对此处定义的Store类进行了重构,以允许使用类构造函数轻松创建多个商店。 因此,此处演示的代码是与特定域存储无关的基本代码。

// src/stores/store.js
…
@action
fetchAll = async() => {
  this.loading = true;
  this.errors = {};
  try {
    const response = await this.service.find({})
    runInAction('entities fetched', () => {
      this.entities = response.data;
      this.loading = false;
    });
  } catch(err) {
      this.handleErrors(err);
  }
}
…

信不信由你,两个版本中定义的逻辑都执行相同的任务,这些任务是:

  • 更新UI加载状态
  • 异步获取数据
  • 捕获异常并更新状态。

在Redux中,我们使用了33行代码 。 在MobX中,我们使用了大约14行代码来达到相同的结果! MobX版本的一个主要优点是,几乎不需要修改就可以在几乎所有域存储类中重用基本代码。 这意味着您可以更快地构建应用程序。

其他差异

为了在Redux中创建表单,我使用了redux-form 。 在MobX中,我使用了mobx-react-form 。 这两个库都很成熟,可以帮助您轻松处理表单逻辑。 我个人更喜欢mobx-react-form ,因为它允许您通过插件验证字段。 使用redux-form ,您可以编写自己的验证代码,也可以导入验证包为您处理验证。

MobX的一个小缺点是,您不能直接访问可观察对象中的某些功能,因为它们并不是真正的普通JavaScript对象。 幸运的是,他们提供了toJS()函数,您可以使用该函数将可观察对象转换为纯JavaScript对象。

结论

显然,您可以看到MobX的代码库要精简得多。 使用OOP风格和良好的开发实践,您可以快速构建应用程序。 主要缺点是编写糟糕,无法维护的代码非常容易。

另一方面,Redux更受欢迎, 非常适合于构建大型和复杂的项目 。 这是一个严格的框架,带有保护措施,可确保每个开发人员都编写易于测试和维护的代码。 但是,它不太适合小型项目。

尽管MobX有很多缺点,但如果遵循良好的做法,您仍然可以构建大型项目。 用爱因斯坦(Albert Einstein)的话来说,“使一切尽可能简单,但不要简单”。

我希望我提供了足够的信息来明确说明是否要迁移到MobX还是坚持使用Redux。 最终,决定取决于您正在处理的项目类型以及可用资源。

本文由Dominic MyersVildan Softic进行了同行评审。 感谢所有SitePoint的同行评审员使SitePoint内容达到最佳状态!


如果您想使用Redux游戏,请注册SitePoint Premium并注册我们的课程Redux Design Issues and Testing 在本课程中,您将构建一个Redux应用程序,该应用程序通过Websocket连接接收按主题组织的推文。 要让您品尝一下商店中的商品,请查看下面的免费课程。

正在加载播放器…

翻译自: https://www.sitepoint.com/redux-vs-mobx-which-is-best/

mobx redux

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值