mobx-react快速入门使用

目录

眼熟一下

Provider

@inject

 @observable

@observer

@action

@computed

完整代码示例 

状态改变和渲染次数的疑惑

最后


注意:本文更多讲的是怎么使用mobx,关于原理等部分只会稍微带过,请查阅MobX中文官网等其他文章。本文使用TypeScript作为示例代码。另外!如果有什么地方说错了,欢迎指正!毕竟俺也是新人~

眼熟一下

首先眼熟一下几个名称:

// mobx最上层声明状态的组件
<Provider></Provider>


// 下面为几个常见的装饰器(decorators),用于定义和管理应用状态和行为
@inject('属性名')

@observable

@observer

@action

@computed

Provider

在 MobX 和 mobx-react 中,Provider 是一个用于将 MobX store 提供给组件树的 React 组件。它是 mobx-react 库提供的一个组件,用于使整个组件树能够访问到应用程序的 MobX 状态。 

import React from 'react';
import { render } from 'react-dom';
import { Provider } from 'mobx-react';
import MyStore from './stores/MyStore'; // 导入你的 MobX store

const myStoreInstance = new MyStore();

const App = () => (
  // 把 myStore 提供给整个后续的组件树,
  // 所有 Provider 的子组件都可以通过 @inject 的注解获取 myStore 
  <Provider myStore={myStoreInstance}>
    {/* 其他组件嵌套在这里 */}
  </Provider>
);

render(<App />, document.getElementById('root'));

myStore当中会有用@observable装饰的属性, 这些属性就是所谓“状态响应”的“状态”。

@inject

这个装饰器用于将MobX的数据源(通常是Store)注入到React组件中。然后你就可以访问Store的一部分或全部(看你注入了多少),使组件能够响应Store状态的变化。

结合Provider的示例代码,下面的示例是把Provider的myStore注入到了当前MyComponent的props中。即:当前MyComponent的props中的myStore和Provider的myStore一致。

注意:这里只使用了@inject注入,说明MyComponent可以主动读取myStore,但是当myStore发生变化的时候,MyComponent并不会被动收到通知去重新渲染。

@inject('myStore')
class MyComponent extends React.Component {
  render() {
    const { propDataFromParent } = this.props;

    return (
      <div>
        <p>Prop Data from Parent: {propDataFromParent}</p>
      </div>
    );
  }
}

 @observable

用于标记状态对象的属性,使其成为可观察的。被@observable标记的属性会被MobX追踪,当它们发生变化时,相关的观察者(使用@observer装饰器的组件)会得到通知并重新渲染。

import { observable } from 'mobx';

class MyStore {
  @observable someData: number = 42;
}

@observer

这个装饰器使React组件成为MobX的观察者(observer),以便在关联的状态发生变化时重新渲染组件。使用@observer装饰器可以让组件订阅相关状态的变化,并在变化时自动重新渲染

这个示例和上文@inject的代码示例的区别就是,该示例多了@observer,那么该示例就可以在myStore中的状态发生变化的时候,自动重新渲染。(具体状态变化和渲染的各种情况,下文会有解释,这里只需要了解observer是能够观察mobx中状态变化的。)

PS:组件会监听自己所有使用的@observable装饰的属性,包括组件内部自己声明的状态。

@inject('myStore')
@observer
class MyComponent extends React.Component {
  render() {
    const { propDataFromParent } = this.props;

    return (
      <div>
        <p>Prop Data from Parent: {propDataFromParent}</p>
      </div>
    );
  }
}

@action

用于标记修改状态的方法。在MobX中,任何改变状态的操作都应该在@action修饰的函数内部进行,以确保状态的一致性和可追踪性。

通过@inject注入到component中的myStore实例,实际上是只读的。也就是说不能在component中直接对myStore的值进行修改,而是使用@action装饰的myStore中的修改状态的方法。

请注意,action是作为一个事务被提交的,也就是说在action中做的变化,会一次性传递给所有的observer,有助于性能优化。请尽量在action中完成一个状态改变的操作。

import { action } from 'mobx';

class MyStore {
  @observable someData: number = 42;

  @action
  updateData(newData: number) {
    this.someData = newData;
  }
}

@computed

用于创建计算属性,这是一种从现有状态派生出的值,其值是根据其依赖的状态的变化而自动更新的。使用@computed装饰器可以创建派生状态,而不需要手动管理其更新逻辑。

这个应用的比较多的场景应该是各种计算之类的,例如组件实际使用的是x属性各种复杂运算之后的数据:

  1. 如果在渲染的时候才对其进行计算,那么每次渲染都需要重新进行复杂运算
  2. 如果使用@computed,那么在下一次渲染使用到这个值的时候,才会进行一次复杂运算返回,并缓存计算结果。后续渲染的时候重新取这个值,只要x属性没变化,将直接取缓存的计算结果。

由此可见,该装饰器在合适场景下能优化性能。

import { computed } from 'mobx';

class MyStore {
  @observable x: number = 10;
  @observable y: number = 20;

  @computed
  get sum(): number {
    return this.x + this.y;
  }
}

完整代码示例 

下面使用一个完整代码示例来梳理一下全文的知识点,可仔细看看注释。

Store:

import { observable, action, computed } from "mobx";

class MyStore {
  // 使用@observable装饰,那么
  // 当name、message发生变化的时候,观察了这两个属性的组件会自动重新渲染
  @observable name = "狗子";
  @observable message = "阿珍爱上了阿强";

  // 使用action装饰,说明该方法会引起状态变化
  // 观察可以看到该方法修改了message状态
  @action
  updateMessage(newMessage: string) {
    this.message = newMessage;
  }

  // 使用computed装饰,会自动重新计算值
  // 此方法:name改变或者message改变,都会引起wholeMessage改变
  @computed
  get wholeMessage() {
    return this.name + " 说: " + this.message;
  }
}

export default MyStore;

APP入口:

import { Provider } from "mobx-react";
import MyStore from "../../store/mystore";
import MyComponent from "../my-component";

const myStoreInstance = new MyStore();

const App = () => (
  // 使用Provider,将myStore提供给整个状态树。
  <Provider myStore={myStoreInstance}>
    <MyComponent />
  </Provider>
);

export default App;

 组件component:

import { inject, observer } from "mobx-react";
import React from "react";
import MyStore from "src/store/mystore";

interface Props {
  myStore?: MyStore;
}

// 用inject将Provider提供的myStore注入到MyComponent的Props中
@inject("myStore")
// 使用observer,则MyComponent会接收到myStore中,所有自己用到的状态改变的信息
@observer
class MyComponent extends React.Component<Props> {
  render() {
    const { myStore } = this.props;
    if (!myStore) {
      return (
        <div>
          <p>啥也没有a </p>
        </div>
      );
    }
    const { name, message } = myStore;

    return (
      <div>
        <p>name: {name}</p>
        <p>message: {message}</p>
        <p>wholeMessage: {myStore?.wholeMessage}</p>
        {/* {调用了updateMessage方法,修改了message值,同时导致整个组件重新渲染了。} */}
        <button onClick={() => myStore?.updateMessage("新消息来咯")}>
          发个新消息aaa?
        </button>
      </div>
    );
  }
}

export default MyComponent;

部分疑惑

状态改变和渲染次数的疑惑

1. 在实际开发中,我有一个疑惑:是不是MyStore的任一属性改变,都会触发MyComponent的重新渲染呢?如果是的话,那当MyStore有较多属性,而MyComponent只用了一两个属性,不就可能会导致MyComponent发生很多不必要的渲染吗?

解答:MyComponent实际上观察的是自己在实际渲染过程中,用到的属性。也就是说当组件只用了a属性,那么当Store的b属性改变的时候,并不会引起组件的重新渲染。

2. 按照1的解答,只有用到的属性会改变会触发重新渲染,那么如果用到的属性没有用@observable装饰呢?

解答:如果没有用@observable装饰属性a,那么a改变不会触发重新渲染。但是,如果使用了@action装饰了修改a的方法,那么最后也会触发重新渲染。

如何做到最小范围组件渲染(最小影响面)

在开发过程中,我们往往一个组件里面包含了非常多的子组件,但是实际上只在部分子组件使用到了可观察状态,那么当这些状态变化的时候,会导致整个组件重新render,怎么样才能做到只渲染使用了可观察状态的组件呢?

  1. 将该部分组件抽出来单独作为一个组件,单独observer,父组件直接引用该子组件。
  2. 如果不想再多一个类或者文件,以下方法可以简写,实际上MyText就相当于一个子组件,这样就能保证当name变化的时候,不会触发整个父组件渲染,只会触发MyText组件渲染。
    MyText = observer(() => {
        console.log(`重新渲染了名字`)
        return (
          <View>
            <Text>{this.myStore.name}</Text>
          </View>
        )
      })

最后

欢迎朋友们指正!

  • 39
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
mobx-react是一个用于将MobxReact框架结合使用的中间件工具。它提供了一些装饰器和高阶组件,使得在React组件中使用Mobx更加方便。通过使用@inject装饰器,我们可以将Mobx的store注入到组件的props中,以便在组件中访问和使用store中的数据。同时,使用@observer装饰器可以将组件转化为观察者,使得组件能够响应store中数据的变化并进行相应的更新。这样,当store中的数据发生变化时,被观察的组件也会相应地进行更新。\[3\] #### 引用[.reference_title] - *1* [mobxreact如何使用](https://blog.csdn.net/weixin_43834567/article/details/118414211)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [React-Mobx(入门)](https://blog.csdn.net/weixin_57844432/article/details/127923571)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [Reactmobxmobx-react 入门](https://blog.csdn.net/sinat_17775997/article/details/82765771)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值