更好用的基于mobx的数据流管理框架:Vane

前端之家收集整理的这篇文章主要介绍了更好用的基于mobx的数据流管理框架:Vane前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

vane

基于mobx & mobx-react的React store管理框架,提供简单快捷开发方式。

项目地址:Vane

特点

三个API搞定问题!简单易上手,开发效率高。

如何使用

vane提供了一键初始化的start方法,入口文件可以像下面这样开始:

  1. import React from 'react';
  2. import App from './App';
  3.  
  4. import {
  5. start,} from 'vane';
  6.  
  7. // model
  8. import user from './models/User';
  9. import todos from './models/Todos';
  10.  
  11. start({
  12. component: App,container: '#root',models: {
  13. user,todos
  14. }
  15. });

所以,只需要把你的model(类似于tarot的module)、React Container Component、Middleware(可选)、Relation传递进来,应用就能跑起来了。

介绍下几个概念:

  • model: 数据管理,区别于tarot,其只有:name命名空间以及data、action两个核心部分,action部分可以同时存放类似于Reducers以及Effects两个部分的操作(作为优化,后续这里可以做拆分);

  • middleware:中间件,用于辅助异步处理。model重定义的一个action最终被执行的流程是这样的:首先其会被mobx的action函数包一层,以避免掉每次更改数据都会触发一次UI的重新渲染,然后其会被各个中间件依次执行,而每个中间件都有before/after/error三个操作,可以在不同的操作中对每一种操作做统一的处理;

  • relation:用于不同model之间的通信,基于监听订阅模式。

基于vane的开发范式的container Component也是UI Component,UI Component像下面这样:

  1. import React,{Component,PropTypes} from 'react';
  2.  
  3. // load middlewares
  4. import './middlewares';
  5.  
  6. // components
  7. import UserLogin from './components/UserLogin';
  8. import UserDetail from './components/UserDetail';
  9. import Todos from './components/Todos';
  10.  
  11. import {
  12. inject,observer,} from 'vane';
  13.  
  14. // 注意先observer,后inject
  15. @inject('user')
  16. @observer
  17. export default class App extends Component {
  18. render() {
  19. // const user = this.props.user.toJSON();
  20. console.log(this.props.user.toJSON());
  21. const {user} = this.props;
  22.  
  23. console.log('user.isLogin:',user.isLogin);
  24.  
  25. if (user.isLogin !== true) {
  26. return <UserLogin />;
  27. }
  28.  
  29. return (
  30. <div>
  31. <UserDetail />
  32. <Todos />
  33. </div>
  34. );
  35. }
  36. }

这里的oberser来自于mobx的observer,inject则来自于mobx-react。如果想给一个Component同时注入多个model,则可以像下面这样:

  1. // start
  2. import React from 'react';
  3. import App from './App';
  4.  
  5. import {
  6. start,todos
  7. }
  8. });
  1. import {
  2. inject,} from 'vane';
  3.  
  4. @inject(
  5. stores => ({
  6. user: stores.user,todos: stores.todos,})
  7. )
  8. @oberser
  9. class MyComponent extends Component{
  10. constructor(props,context) {
  11. super(props,context);
  12. }
  13.  
  14. render() {
  15. const {
  16. user,todos,} = this.props;
  17.  
  18. return (
  19. <div>{user.name}</div>
  20. );
  21. }
  22. }

mobx的observer API,用于将React Component变成observable的(动态收集依赖),在对model中的某些数据做了操作之后,如果被修改的数据刚好被该React组件使用到了,就会触发该组件的重新渲染,这也就是mobx能细粒度控制数据的原因所在。

mobx-react的inject API,用于指定将哪些model注入进React Component(this.props.modelName),也就指定了该组件基于哪些数据做Observeable。

model

代码类似于下面这样:

  1. import TodoItem from './TodoItem';
  2. import * as api from '../api';
  3.  
  4. export default {
  5. name: 'Todos',data: {
  6. list: [],},syncs: {
  7. add(text,userId) {
  8. // 类似于Vue,对数组的操作会触发UI的重新渲染
  9. this.list.push(new TodoItem({
  10. text,userId
  11. }));
  12. },effects: {
  13. async getByUserId(userId) {
  14. let todos = await api.getTodosByUserId(userId);
  15. todos = todos.map(todo => new TodoItem(todo));
  16. // 类似于Vue,对数组的操作会触发UI的重新渲染
  17. this.list = this.list.concat(todos);
  18. },}
  19. };

model由以下几个部分组成:

  • 1、name: 当前model的命名空间;

  • 2、constants: 不可变常量;

  • 3、data: 可操作数据部分;

  • 4、syncs: 同步操作数据部分;

  • 5、effects: 异步处理部分;

  • 6、init: 初始化model后的回调方法

  • 7、autorun: 每次对数据进行操作后都会自动执行的方法

触发action

model内部触发

model内部定义的Data数据,会被赋值到model实例上,所以任何在Data中定义的数据都可以通过this.xxx的方式来引用,如下:

  1. import fetch from 'whatwg-fetch';
  2.  
  3. const pageSize = 20;
  4.  
  5. export default {
  6. name: 'Applications',data: {
  7. dataSource: [
  8.  
  9. ],// 列表显示的数据
  10.  
  11. detailPageVisible: false,campaignDetail: {},syncs: {
  12. validate(value) {
  13. value = value ||'';
  14.  
  15. // xxxx
  16.  
  17. return {
  18. code: 200
  19. };
  20. },effects:{
  21. async getList(payload = {}) {
  22. const {
  23. currentPage = 1,} = payload;
  24.  
  25. const url = `/applications/list/${currentPage}?pageSize=${pageSize}`;
  26.  
  27. let res = await fetch(url);
  28.  
  29. res = res.body;
  30.  
  31. const validateRes = this.validate(res);
  32.  
  33. if(validateRes.code == 200) {
  34. this.dataSource = res.data; // 这样就会触发对应Component的重新渲染
  35. this.currentPage = res.currentPage;
  36. this.totalItem = res.totalItem;
  37. this.totalPage = res.totalPage;
  38. }
  39.  
  40. return res;
  41. },}
  42. };

可以看到,更改数据则是直接给model实例赋值即可,简单直接高效,而且多次赋值只会触发一次的重新渲染。你能想象如果一个页面是一个list列表,用户对列表中某一个进行操作后,需要修改这一项的数据及显示,只需要执行类似于:

  1. this.props.home.list[2].name = 'New Name';

代码就能完成name的数据处理及页面展示更改吗?想想就激动是不是。

组件内触发

如下,简单直接:

  1. import { inject,observer } from 'vane';
  2.  
  3. @inject('applications')
  4. @observer
  5. class Applications extends Component {
  6. constructor(props,context);
  7. }
  8.  
  9. clickHandler() {
  10. this.props.applications.getList(); // 直接执行
  11. }
  12.  
  13. render() {
  14. return (
  15. <div onClick={::this.clickHandler}></div>
  16. );
  17. }
  18. }

开发组件

有时候,我们并不想执行页面渲染,而是用Vane来开发一个组件,这时,还是可以使用start API,只要不传如container值,就会返回一个React Component。

  1. import React from 'react';
  2. import { render } from 'react-dom';
  3. import App from './App';
  4.  
  5. // load middlewares
  6. import middlewares from './middlewares';
  7.  
  8. import {
  9. start,} from 'vane';
  10.  
  11. // model
  12. import user from './models/User';
  13. import todos from './models/Todos';
  14.  
  15. // relation
  16. import relation from './relations';
  17.  
  18. // 验证start返回一个组件
  19. const MyComponent = start({
  20. component: App,todos
  21. },middlewares,relation
  22. });
  23.  
  24. render(<MyComponent data={{a: 1}} />,document.querySelector('#root'));

特点

  • 简单易上手,开发效率高;

  • MVVM:Vane实现了基于React的MVVM开发范式,简单直接,开发效率高;

  • 更改store数据:直接赋值;

  • 触发action:直接执行store的action;

  • 性能优化:自动做掉。

具体例子参考example.

为什么基于mobx的开发范式更简单高效?

Mobx的实现思想和Vue几乎一样,所以其优点跟Vue也差不多:通过监听数据(对象、数组)的属性变化,可以通过直接在数据上更改就能触发UI的渲染,从而做到MVVM、响应式、上手成本低、开发效率高,在数据管理上需要再详细阐述下其区别。

Redux是建议全局唯一Store的,多个Reducers也会在传递给react-redux之前被合并成一个root reducer,任何数据的更改(通过Reducer)都会通过这一个store来触发整个UI树的重新渲染,如果不做任何的性能优化(pureRender等),就算VD(Virtual Dom)有了再高的效率提升,当页面数据量、DOM数量大了,性能消耗也是非常大的。另外一点,Redux实现的对数据的管理是pull方式的,就是说其只能等待应用派发某个行为(Action),然后重新触发UI的渲染,而做不到对行为的可预期;Mobx则不一样,他是基于监听数据的属性变化来实现的,而且是多store的,对于任何的数据变更都是第一时间知道的,所以其实现方式是基于push的监听订阅模式而实现,这样,他就可以做到对数据的可预测以及细粒度的控制,甚至可以通过修改React组件生命周期的方式来减少性能的消耗,而无需使用者对这些细节关心。当然这一切肯定是有了mobx对组件做observe操作才能实现的,所以也就有了observer用的越多,应用性能越高的说法。

感谢

Vane的部分实现参考自MVVM框架:mobx-roof

猜你在找的React相关文章