mobx在react中的使用

mobx在react中的使用步骤

安装依赖包

复制npm i mobx-react@6.1.3 mobx@5.13.0
# or
yarn add mobx-react@6.1.3 mobx@5.13.0

核心api

定义可观察数据

假设声明可观察数据的文件名为test.js

方式一

使用observable()函数

import { observable } from 'mobx';

export default observable({
    name: 'xxxx',
    age: 20
})

方式二

使用在class上使用装饰器

class Test {
    @observable name = '123'
    @observable age = 20
}

export default new Test();

声明要监测数据的视图

在视图中使用的可观察数据发生变化后,mobx会使当前使用可观察数据的组件重新渲染

类组件

使用@observer装饰器.如果TestComponent组件中使用的可观察数据发生变化,该组件会被重新渲染。
只能监测当前组件,不能深入子组件。想要深入子组件,需要子组件使用@observer

import { observer } from 'mobx-react'
import MobxData from './test.js'
@observer
class TestComponent extends React.Component {
    render() {
        // use observable data
        return <div>{MobxData.name}</div>
    }
}

函数式组件

使用useObserver()或者observer()只能监测当前包裹的内容,不能深入子组件。想要深入子组件,需要子组件使用useObserver()observer()

import { useObserver } from 'mobx-react';
import MobxData from './test.js'
const TestComponent = observer(() => {
    // use observable data
    return <div>{MobxData.name}</div>
});

// function TestComponent() {
//    // use observable data
//    return useObserver(() => <div>{MobxData.name}</div>);
// });

代码实现

使用函数式组件演示

定义共享数据

import { action, observable } from "mobx";

// 使用装饰器
// class MobxData {
//   @observable name = 'zoe';
//   @observable age = 12

//   @action.bound
//   setName(name: string) {
//     this.name = name
//   }

// }

// export default new MobxData()

export default observable({
  name: 'xxx',
  age: 18
})

创建组件

import React from 'react'
import {useObserver} from 'mobx-react'
import commonData from './MobxData'

function Child () {
  const onClick = () => {
    commonData.name = Math.random() * 100 + '_zhangsan'
  }
  console.log('child render')
  return useObserver(() => (
    <div>
        Welcome {commonData.name}!You're 12 years old.
        <button onClick={onClick}>change name</button>
    </div>
  ))
}
function Child2 () {
  const onClick = () => {
    commonData.age = Math.random() * 100
  }
  console.log('child2 render')
  return useObserver(() => (
    <div>
        Welcome xxx!You're {commonData.age} years old.
        <button onClick={onClick}>change age</button>
    </div>
  ))
}

// const Child2 = observer(() => {
//   const onClick = () => {
//     commonData.age = Math.random() * 100
//   }
//   console.log('child2 render')
//   return (
//     <div>
//         Welcome xxx!You're {commonData.age} years old.
//         <button onClick={onClick}>change age</button>
//     </div>
//   )
// })

function Parent() {
  return useObserver(() => (<>
    <Child/>
    <Child2/>
    <button onClick={() => {
      commonData.name = Math.random() * 100 + '_qweqweqwe'
    }}>修改名字</button>
    </>))
}

// const Parent = observer(() => (
//   <>
//     <Child/>
//     <Child2/>
//     <button onClick={() => {
//       commonData.name = Math.random() * 100 + '_qweqweqwe'
//     }}>修改名字</button>
//   </>
// ))

// @observer
// class Parent extends React.Component{
//   render() {
//     return (
//       <>
//         <Child/>
//         <Child2/>
//         <button onClick={() => {
//           commonData.name = Math.random() * 100 + '_qweqweqwe'
//         }}>修改名字</button>
//       </>
//     )
//   }
// }

export default function App() {
  return (
    <div>App
      <Parent/>
    </div>
  )
}

主文件

import ReactDOM from 'react-dom'
import Parent from './Parent'


ReactDOM.render(<Parent />, document.querySelector('#root'))

总结

  • 起一个文件,使用mobxobservable()或者@observable创建共享数据并导出
  • 在视图中使用mobx-reactuseObserver()或者observer()或者@observer监测组件中可观察数据的变化
    • 在某组件使用的可观察数据发生变化时该组件会被rerender

填脑坑

@action@action.bound有什么区别?

示例代码

import { action } from "mobx";
class Store {
  unbound() {
    console.log('unbound', this)
  }
  arrow = () => {
    console.log('arrow', this)
  }
  @action unboundAction() {
    console.log('unboundAction', this)
  }
  @action.bound unboundActionBound() {
    console.log('unboundActionBound', this)
  }
  @action arrowAction = () => {
    console.log('arrowAction', this)
  }      
  @action.bound arrowActionBound = () => {
    console.log('arrowActionBound', this)
  }
}

const store = new Store();
const unbound = store.unbound;
const arrow = store.arrow;
const unboundAction = store.unboundAction;
const arrowAction = store.arrowAction;
const unboundActionBound = store.unboundActionBound;
const arrowActionBound = store.arrowActionBound;
console.log(store)
unbound();
arrow();
unboundAction();
arrowAction();
unboundActionBound();
arrowActionBound();

运行后,可以看到日志输出如下

image.png

对原型的影响:

image.png

对this的影响

image.png

但是mobx不推荐action.bound和箭头函数一起使用

注意: action.bound 不要和箭头函数一起使用;箭头函数已经是绑定过的并且不能重新绑定。

useObserver()observer()的区别?

  • useObserver()在函数内使用。监测函数的返回值,使用方式像useMemo
  • observer()在函数外使用。监测高阶组件,使用方式像React.memo

以函数式组件为例

const Parent = observer(() => (
  <>
    <Child/>
    <Child2/>
    <button onClick={() => {
      commonData.name = Math.random() * 100 + '_qweqweqwe'
    }}>修改名字</button>
  </>
))

function Parent() {
  return useObserver(() => (
    <>
      <Child/>
      <Child2/>
      <button onClick={() => {
        commonData.name = Math.random() * 100 + '_qweqweqwe'
      }}>修改名字</button>
    </>
  ))
}

参考链接

action (动作)

React 状态管理工具 Mobx 基本使用_。烦啦的博客-程序员秘密

https://stackoverflow.com/questions/48639891/difference-between-mobxs-action-bound-and-arrow-functions-on-class-functions

posted @   酉云良  阅读(868)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
历史上的今天:
2021-10-15 CSS3动画使用笔记
2021-10-15 VScode中Node.js使用babel运行ES6模块机制
点击右上角即可分享
微信分享提示