mobx和mobx-react 入门

8,950 阅读1分钟

1.为什么需要状态管理?

组件内

  • class组件state
  • 函数组件useState

组件间

  • 父子之间通信用props传递
  • 爷孙之间通信传递两次props
  • 但是任意组件?

这个时候我们就需要用到mobx和mobx-react(这里不讲redux)

2.mobx

核心概念

文档

mobx中文文档

基本用法

  • State
import { observable, computed, action, autorun } from "mobx";
//State,被观察者
const todos = (observable([
 {
 title: "起床",
 completed: false
 },
 {
 title: "穿⾐",
 completed: false
 },
 {
 title: "洗漱",
 completed: false
 }
]));
  • Computed
//Computed values ,由 State 的更新触发
let uncompletedCount = computed(
() => todos.filter(todo => !todo.completed).length
);
  • Reactions
//Reactions, 由 State 和 Computed Values 的改变触发执⾏
autorun(() => {
console.log(
`剩余任务:${uncompletedCount}`,
todos
.filter(todo => !todo.completed)
.map(todo => todo.title)
.join(", ")
);
});
  • Actions
const doTask = action(() => {
todos.find(todo => !todo.completed).completed = true
});
doTask()

装饰器

什么是装饰器 Decorators

  • 核⼼思想:保留原来的名字和主功能,添加⼀ 些附庸功能
  • ⼀种设计模式,⽤来“装饰”⼀个函数或对象
  • ES7 新语法,⽤来装饰类或者属性

@observable 可以在实例字段和属性 getter 上使用。 对于对象的哪部分需要成为可观察的,@observable 提供了细粒度的控制。

import { observable, computed } from "mobx";

class OrderLine {
    @observable price = 0;
    @observable amount = 1;

    @computed get total() {
        return this.price * this.amount;
    }
}

mobx 的装饰器写法

import { observable, autorun, computed, action } from 'mobx';
class Todo {
 @observable todos = []
 constructor() {
 autorun(() => {
 console.log(
 `剩余任务:${this.uncompletedCount}`,
 this.todos
 .filter(todo => !todo.completed)
 .map(todo => todo.title)
 .join(", ")
 );
 });
 }
 @computed get uncompletedCount() {
 return this.todos.filter(todo => !todo.completed).length;
 }
 @action addTodo(title) {
 this.todos.push({
 title: title,
 completed: false
 });
 }
 @action doTask(){
 this.todos.find(todo => !todo.completed).completed = true
 }
}

核心思想

状态的改变引发⼀系列⾃动⾏为

React项⽬中使⽤装饰器

  • yarn eject
  • yarn add @babel/plugin-proposal-decorators
  • 修改package.json, 找到 babel字段, 添加"plugins": [ "@babel/plugin-proposal-decorators" ]

3.mobx-react

在Class组件使⽤mobx

  • 设置Store
import { observable, action } from 'mobx';
class AboutStore {
 @observable counter = 1;
 @action add() {
 this.counter++;
 }
}
export default new AboutStore;
  • 提供数据源
import { Provider } from 'mobx-react';
ReactDOM.render(
 <React.StrictMode>
 <Router>
 <Provider homeStore={homeStore} aboutStore={aboutStore}>
 <App />
 </Provider>

 </Router>
 </React.StrictMode>,
 document.getElementById('root')
);
  • 使用数据源
import { observer, inject } from 'mobx-react';
@inject('aboutStore')
@inject('homeStore')
@observer
class About extends Component {
 render() {
 return (
 <div>
 <h1>About</h1>
 <p>current counter : {this.props.aboutStore.counter}</p>
 <p>home counter: {this.props.homeStore.counter}</p>
 <Link to="/">去⾸⻚</Link>
 </div>
 );
 }
}

在函数组件使⽤mobx

  • 设置Store
import { observable, action, computed } from 'mobx';
export class HomeStore {
 @observable counter = 1;
 @computed get doubleCounter() {
 return this.counter * 2;
 }
 @action add() {
 this.counter++;
 }
}
  • 创建Context 对象
import React from 'react';
import { HomeStore } from '../stores/home';
import { AboutStore } from '../stores/about';
export const storesContext = React.createContext({
 homeStore: new HomeStore(),
 aboutStore: new AboutStore()
});
  • useContext

设置useStores函数,⽤于在函数组件 内获取context对象

import React from 'react';
import { storesContext } from '../contexts';
export const useStores = () => React.useContext(storesContext);
  • 使⽤context

观察组件,通过useStore获取context 对象

import React, { Component } from 'react';
import { observer } from 'mobx-react';
import { useStores } from '../hooks/use-stores';
const About = observer(() => {
 const { homeStore, aboutStore } = useStores();
 return (
 <div>
 <h1>About</h1>
 <p>current counter : {aboutStore.counter}</p>
 <p>home counter: {homeStore.counter}</p>
 </div>
 )
}

参考