React 之 MobX 5-6

React 之 MobX 5-6

1.1、MobX

简单,可扩展的状态管理库

MobX 是由 Mendi, Coinbase, Facebook 开源和众多个人赞助商所赞助的

React 和 MobX 是一对强力组合,React 负责渲染应用的状态,MobX 负责管理应用状态供 React 使用

1.2、MobX 浏览器支持

MobX5 版本运行在任何支持 ES6 proxy 的浏览器,不支持 E11,Node.js6

MobX4 可以运行在任何支持 ES5 的浏览器上

MobX4 和 5 的 API 是相同的

2、开发前需要配置装饰器语法

2.1方式一: 启用装饰器语法支持
  1. 弹射项目底层配置:npm run eject
  2. 下载装饰器语法 babel:插件:npm install @babel/plugin-proposal-decorators
  3. 在 package, json 文件中加入配置
"babel": {
    "plugins": [
        [
            "@babel/plugin-proposal-decorators",
            {
                "legacy": true
            }
        ]
    ]
}
2.2方式二: 启用装饰器语法支持
  1. npm install react-app-rewired @babel/plugin-proposal-decorators customize-cra
  2. 在项目根目录下创建 config-overrides.js 并加入配置
const { override, addDecoratorsLegacy } = require("customize-cra");
module.exports = override(addDecoratorsLegacy());
  1. 更改 package.json 文件中的配置项
"scripts": {
  "start": "react-app-rewired start",
    "build": "react-app-rewired build",
    "test": "react-app-rewired test",
}

解决vscode编辑器关于装饰器语法的警告
“javascript.implicitProjectConfig.experimentalDecorators”: true

MobX 工作流

在这里插入图片描述

MobX 6

1. MobX 6 概述
  • MobX 是一个简单的可扩展的状态管理库,无样板代码风格简约。

  • 目前最新版本为 6,版本 4 和版本 5 已不再支持。

  • 在 MobX 6 中不推荐使用装饰器语法,因为它不是 ES 标准,并且标准化过程要花费很长时间,但是通过配置仍然可以启用装饰器语法。

  • MobX 可以运行在任何支持 ES5 的环境中,包含浏览器和 Node。

  • MobX 通常和 React 配合使用,但是在 AngularVue 中也可以使用 MobX。

2. MobX 6 使用
2.1 下载
  • mobx:MobX 核心库
  • mobx-react-lite:仅支持函数组件(建议使用函数组件)
  • mobx-react:既支持函数组件也支持类组件

yarn add mobx@6.1.8 mobx-react-lite@3.2.0

2.2 核心概念
  1. observable state:被 MobX 跟踪的状态。
  2. action:允许修改状态的方法,在严格模式下只有 action 方法被允许修改状态。
  3. computed:根据应用程序状态派生的新值,计算值。
2.3 工作流程

在这里插入图片描述

2.4一个简单例子
import React from "react"
import ReactDOM from "react-dom"
import { makeAutoObservable } from "mobx"
import { observer } from "mobx-react"

// 对应用状态进行建模。
class Timer {
    secondsPassed = 0

    constructor() {
        makeAutoObservable(this)
    }

    increase() {
        this.secondsPassed += 1
    }

    reset() {
        this.secondsPassed = 0
    }
}

const myTimer = new Timer()

// 构建一个使用 observable 状态的“用户界面”。
const TimerView = observer(({ timer }) => (
    <button onClick={() => timer.reset()}>已过秒数:{timer.secondsPassed}</button>
))

ReactDOM.render(<TimerView timer={myTimer} />, document.body)

// 每秒更新一次‘已过秒数:X’中的文本。
setInterval(() => {
    myTimer.increase()
}, 1000)
2.4.1 makeAutoObservable
// target: 将目标对象中的属性和方法设置为 observable state 和 action
// overrides: 覆盖默认设置, 将 target 对象中的某些属性或者方法设置为普通属性
// options: 配置对象, autoBind, 使 action 方法始终拥有正确的 this 指向
makeAutoObservable(target, overrides?, options?)
makeAutoObservable(this, {reset: false}, {autoBind: true})
2.4.2 总结

状态变化更新视图的必要条件

  1. 状态需要被标记为 observable state
  2. 更改状态的方法需要被标记为 action 方法
  3. 组件视图必须通过 observer 方法包裹

可以使用 makeAutoObservable 方法将对象属性设置为 observable state,将对象方法设置为 action 方法

可以使用 observer 方法监控当前组件使用到的由 MobX 跟踪的 observable state,当状态发生变化时通知 React 更新视图

3 常用API
3.1 makeObservable
 import { action, makeObservable, observable } from "mobx"
   
   class TodoListStore {
     constructor() {
       makeObservable(this, {
         todos:  observable,  //数据观察
         createTodo:  action,  //数据操作
         totle:  computed,  //计算属性 
         ....
       })
     }
   }
3.2 computed

计算属性 当依赖状态发生变化后,计算值自动更新。

import { computed } from "mobx"

class TodoListStore {
  constructor() {
    makeObservable(this, {
      unCompletedTodoCount: computed
    })
  }
  get unCompletedTodoCount() {
    return this.todos.filter(todo => !todo.completed).length
  }
}

注意:计算值是被缓存的。

get unCompletedTodoCount() {
  console.log("unCompletedTodoCount")
  return this.todos.filter(todo => !todo.completed).length
}
{todoListStore.unCompletedTodoCount}
{todoListStore.unCompletedTodoCount}
{todoListStore.unCompletedTodoCount}
// 计算属性被调用多次, 但是方法内部的console.log 只会输出一次, 说明计算属性是被缓存的.
3.3 runInAction 方法

异步方法不可以作为action方法,需要使用 runInAction 处理

import {
  runInAction
} from "mobx"
   
class TodoListStore {
  async loadTodos() {
    let todos = await axios
      .get("http://localhost:3005/todos")
      .then(response => response.data)
    runInAction(() => {
      todos.forEach(todo => {
        this.todos.push(new TodoStore(todo.title))
      })
    })
  }
}
3.4 autorun 方法
  1. 监控数据变化执行副作用,接收一个函数作为参数,参数函数用来执行副作用,当参数函数内部使用的 observable state, computed 发生变化时函数会运行,初始运行 autorun 方法时参数函数也会运行一次。
import { autorun } from "mobx"
import { useEffect } from "react"

function Counter() {
  const { counterStore } = useRootStore()
  useEffect(() => {
    // 确保 autorun 方法只被初始化一次
    autorun(() => {
      console.log(counterStore.count)
    })
  }, [])
}
  1. 对于基本数据类型,属于值传递,mobx 只能跟踪到原始属性,跟踪不到复制后的值。
useEffect(() => {
let count = counterStore.count
autorun(() => {
  // 错误写法, mobx 跟踪不到变量 count
  console.log(count)
})
}, [])
  1. 对于引用数据类型,只要引用地址不发生变化,mobx 就可以进行跟踪
3.5 reaction 方法

监控状态变化执行副作用,接收两个函数作为参数,第一个函数返回要监控的状态,第二个函数用来执行副作用,只有当第一个函数返回的状态发生变化时,第二个函数才会执行。reaction 方法提供了更加细颗粒度的状态控制。

和 autorun 不同,reaction 初始时不会执行副作用。

import { reaction } from "mobx"

function Counter() {
	useEffect(() => {
  	reaction(
      () => counterStore.count,
      (current, previous) => {
        console.log(current)
        console.log(previous)
      }
    )
  }, []) 
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值