{"id":19069617,"url":"https://github.com/srect/mobx-demo","last_synced_at":"2025-07-11T07:07:08.995Z","repository":{"id":114172752,"uuid":"352913812","full_name":"sRect/mobx-demo","owner":"sRect","description":"mobx and mobx-react-lite demo","archived":false,"fork":false,"pushed_at":"2021-03-31T08:10:34.000Z","size":94,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-02-22T03:41:58.425Z","etag":null,"topics":["mobx","mobx-react","mobx-react-lite"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sRect.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-03-30T07:43:06.000Z","updated_at":"2021-04-01T09:01:13.000Z","dependencies_parsed_at":null,"dependency_job_id":"a0223ddf-5edb-4058-b789-41d8533c69fd","html_url":"https://github.com/sRect/mobx-demo","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/sRect/mobx-demo","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sRect%2Fmobx-demo","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sRect%2Fmobx-demo/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sRect%2Fmobx-demo/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sRect%2Fmobx-demo/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sRect","download_url":"https://codeload.github.com/sRect/mobx-demo/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sRect%2Fmobx-demo/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":263145905,"owners_count":23420681,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["mobx","mobx-react","mobx-react-lite"],"created_at":"2024-11-09T01:14:56.658Z","updated_at":"2025-07-02T13:08:14.129Z","avatar_url":"https://github.com/sRect.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"### 1. 写在前面\n本文会介绍`mobx`、`mobx-react`和`mobx-react-lite`的基本使用，还有配合`react context api`的使用，都是api的入门使用，不涉及源码剖析。\n\n### 2. 什么是Mobx？\n1. [Simple, scalable state management](https://www.npmjs.com/package/mobx)\n2. [MobX is a battle tested library that makes state management simple and scalable by transparently applying functional reactive programming (TFRP)](https://www.npmjs.com/package/mobx)\n\n**Mobx是简单、可扩展的状态管理库**。是经过战斗洗礼的库，通过透明的函数响应式编程使状态管理变得更加简单且可扩展。说明Mobx足够可靠，可放心在项目中使用。\n\n![](https://files.mdnice.com/user/7771/65947f38-7023-4875-8d57-46b414ab2cac.png)\n\n上图所示，**Mobx是通过`event`事件调用`action`，修改`observal state`数据，进而触发`computed`，使其自动更新数据，`Reactions`是对state的改变做出的反应，以此更新视图，这是Mobx的核心所在**。\n\n\n### 3. **mobx**的使用\n\n\u003e mobx 为 6.x 版本，常用api的使用\n\n#### 3.1 使用`makeObservable`\n\n```javascript\nimport {\n  makeObservable,\n  observable,\n  action,\n  computed,\n  autorun,\n  reaction,\n  when,\n} from \"mobx\";\n\n// 创建store\nconst store = makeObservable(\n  {\n    count: 1,\n    get double() {\n      return this.count * 2;\n    },\n    increment() {\n      // 定义action\n      this.count += 1;\n    },\n    decrement() {\n      this.count -= 1;\n    },\n  },\n  {\n    count: observable, // 需要响应的属性\n    double: computed, // 计算属性\n    increment: action, // action\n    decrement: action,\n  }\n);\n\nclass MobxDemo {\n  constructor() {\n    this.increaseBtn = document.querySelector(\"#increaseBtn\");\n    this.decreaseBtn = document.querySelector(\"#decreaseBtn\");\n    this.container = document.querySelector(\".container\");\n  }\n\n  handleRefresh() {\n    this.container.innerHTML = `\n      count: ${store.count}\n      double count: ${store.double}\n    `;\n  }\n\n  init() {\n    this.handleRefresh();\n    this.increaseBtn.addEventListener(\"click\", () =\u003e {\n      store.increment();\n    });\n    this.decreaseBtn.addEventListener(\"click\", () =\u003e {\n      store.decrement();\n    });\n\n    // autorun类似于react hooks中的useEffect\n    // 当observable响应属性被更新时，autorun立即被调用一次\n    autorun(() =\u003e {\n      this.handleRefresh();\n    });\n\n    // 类似Vue中的watch观察\n    reaction(\n      () =\u003e store.count, // 指定观察count属性\n      (currentVal, oldVal) =\u003e {\n        console.log(`current: ${currentVal}, old: ${oldVal}`);\n      }\n    );\n\n    // 条件响应\n    when(\n      () =\u003e store.count \u003c 0,\n      () =\u003e {\n        console.log(\"count小于0\");\n      }\n    );\n  }\n}\n\nconst mobxDemo = new MobxDemo();\nmobxDemo.init();\n```\n\n#### 3.2 使用`makeAutoObservable`\n\n\u003e 相比`makeObservable`,`makeAutoObservable`就简化多了，无需再手动指定observable、action、computed\n\n```javascript\nimport { makeAutoObservable, autorun, runInAction } from \"mobx\";\n\n// 直接使用makeAutoObservable\nconst store = makeAutoObservable({\n  count: 1,\n  get double() {\n    return this.count * 2;\n  },\n  increment() {\n    this.count += 1;\n  },\n  decrement() {\n    this.count -= 1;\n  },\n  // 在 MobX 中，不管是同步还是异步操作，都可以放到 action 中，\n  // 只是异步操作在修改属性时，需要将赋值操作放到 runInAction 中。\n  async asyncDecreament() {\n    // 模拟ajax获取数据\n    const count = await new Promise((resolve) =\u003e {\n      setTimeout(() =\u003e resolve(1), 500);\n    });\n    // 获取数据后，将赋值操作放到 runInAction 中\n    runInAction(() =\u003e {\n      this.count -= count;\n    });\n  },\n});\n```\n\n#### 3.3 使用 6.x 版本之前的 decorator 装饰器写法\n\n使用装饰器步骤:\n1. 安装依赖 `npm i @babel/plugin-proposal-decorators -D`\n2. 在`.babelrc`配置文件`plugins`顶部添加`[\"@babel/plugin-proposal-decorators\", {\"legacy\": true}],`装饰器配置\n3. 如果`vsCode编辑器`显示装饰器语法报错，在项目根目录添加`jsconfig.json`文件，输入`{\"compilerOptions\": {\"experimentalDecorators\": true}}`，重启编辑器即生效\n\n```javascript\nimport { observable, action, computed } from \"mobx\";\n\nclass Store {\n  @observable count = 0;\n  constructor() {\n    makeObservable(this);\n  }\n\n  @computed get double() {\n    return this.count * 2;\n  }\n\n  @action increment() {\n    this.count++;\n  }\n\n  @action decrement() {\n    this.count--;\n  }\n}\n\nconst store = new Store();\n```\n\n### 4. **mobx-react-lite**的使用\n\n\u003e `mobx-react-lite`是`mobx-react`的轻量化版本，在`mobx-react@6`版本中已经包含了`mobx-react-lite`，但是如果只在函数式组件中使用，推荐使用轻量化的`mobx-react-lite`\n\n#### 4.1 父组件使用`useLocalObservable`创建store，配合React提供的`Context`传递store\n\n```javascript\nimport React, { createContext } from \"react\";\nimport { observer, useLocalObservable } from \"mobx-react-lite\";\nimport Child1 from \"@/component/Child1\";\nimport Child2 from \"@/component/Child2\";\nimport Child3 from \"@/component/Child3\";\n\nexport const Context = createContext(null);\n\nconst Parent = () =\u003e {\n  // 'useLocalStore' is deprecated, use 'useLocalObservable' instead.\n  const storeContext = useLocalObservable(() =\u003e ({\n    count: 1,\n    get double() {\n      return this.count * 2;\n    },\n    increase() {\n      this.count += 1;\n    },\n    decrease() {\n      this.count -= 1;\n    },\n  }));\n\n  return (\n    \u003cdiv\u003e\n      \u003cContext.Provider value={storeContext}\u003e\n        \u003cChild1 /\u003e\n        \u003cChild2 /\u003e\n        \u003cChild3 /\u003e\n      \u003c/Context.Provider\u003e\n    \u003c/div\u003e\n  );\n};\n\nexport default observer(Parent);\n```\n\n#### 4.2 子组建为 function 组件(**使用Context**)\n\n```javascript\nimport React, { useContext, useEffect } from \"react\";\nimport { observer } from \"mobx-react-lite\";\nimport { toJS, reaction, when } from \"mobx\";\nimport { Context } from \"@/App\";\n\nconst Child1 = () =\u003e {\n  const store = useContext(Context);\n\n  useEffect(() =\u003e {\n    console.log(\"store===\u003e\", toJS(store));\n\n    reaction(\n      () =\u003e store.count,\n      (cur, pre) =\u003e {\n        console.log(`cur: ${cur}, pre: ${pre}`);\n      }\n    );\n\n    when(\n      () =\u003e store.count \u003c 0,\n      () =\u003e {\n        console.log(\"小于0\");\n      }\n    );\n  }, [store]);\n\n  // [mobx-react-lite] 'useObserver(fn)' is deprecated.\n  // Use `\u003cObserver\u003e{fn}\u003c/Observer\u003e` instead, or wrap the entire component in `observer`.\n  // return useObserver(() =\u003e (\n  return (\n    \u003cdiv\u003e\n      \u003ch2\u003efunction Child1 page\u003c/h2\u003e\n      count: {store?.count} \u003cbr /\u003e\n      double: {store?.double}\n      \u003cbr /\u003e\n      \u003cbutton onClick={() =\u003e store.increase()}\u003eincrease\u003c/button\u003e\n      \u0026nbsp;\n      \u003cbutton onClick={() =\u003e store.decrease()}\u003edecrease\u003c/button\u003e\n    \u003c/div\u003e\n    // ));\n  );\n};\n\n// export default Child1;\nexport default observer(Child1);\n```\n\n#### 4.3 子组建为 function 组件(**不使用Context**)\n\n\u003e 不使用 Context，就要用到`mobx-react`,看 *5.3* 部分\n\n#### 4.4 子组件为 class 组件\n\n\u003e 通过`Context.Consumer`组件获取到store\n\n```javascript\nimport React, { Component } from \"react\";\nimport { Observer } from \"mobx-react-lite\";\nimport { Context } from \"@/App\";\n\nclass Child3 extends Component {\n  render() {\n    return (\n      \u003cdiv\u003e\n        \u003cContext.Consumer\u003e\n          {(store) =\u003e (\n            \u003cdiv\u003e\n              \u003ch5\u003eclass Child3 page\u003c/h5\u003e\n              {/* count: {store?.count} \u003cbr /\u003e\n              double: {store?.double} */}\n              {/* 必须使用Observer包裹，否则视图不会更新 */}\n              \u003cObserver\u003e{() =\u003e \u003cdiv\u003ecount: {store?.count}\u003c/div\u003e}\u003c/Observer\u003e\n              \u003cObserver\u003e{() =\u003e \u003cdiv\u003edouble: {store?.double}\u003c/div\u003e}\u003c/Observer\u003e\n              \u003cbr /\u003e\n              \u003cbutton onClick={() =\u003e store.increase()}\u003eincrease\u003c/button\u003e\n              \u0026nbsp;\n              \u003cbutton onClick={() =\u003e store.decrease()}\u003edecrease\u003c/button\u003e\n            \u003c/div\u003e\n          )}\n        \u003c/Context.Consumer\u003e\n      \u003c/div\u003e\n    );\n  }\n}\n\nexport default Child3;\n```\n\n### 5. **mobx-react**的使用\n\n#### 5.1 父组件用`mobx-react`提供的`Provider组件`向下传递store\n\n```javascript\nimport React from \"react\";\nimport { Provider } from \"mobx-react\";\nimport { useLocalObservable } from \"mobx-react-lite\";\nimport Child1 from \"@/component/Child1\";\nimport Child2 from \"@/component/Child2\";\n\nconst Parent = () =\u003e {\n  // 也可以使用mobx创建一个store，这里为了方便，直接使用了useLocalObservable\n  const storeContext = useLocalObservable(() =\u003e ({\n    count: 1,\n    get double() {\n      return this.count * 2;\n    },\n    increase() {\n      this.count += 1;\n    },\n    decrease() {\n      this.count -= 1;\n    },\n  }));\n\n  return (\n    \u003cdiv\u003e\n      \u003cProvider store={storeContext}\u003e\n        \u003cChild1 /\u003e\n        \u003cChild2 /\u003e\n      \u003c/Provider\u003e\n    \u003c/div\u003e\n  );\n};\n\nexport default observer(Parent);\n```\n\n#### 5.2 子组件为 class 组件\n\n```javascript\nimport React from \"react\";\nimport { observer, inject } from \"mobx-react\";\n\n@inject(\"store\")\n@observer\nclass Child1 extends React.Component {\n  render() {\n    \u003cdiv\u003e\n      \u003ch5\u003eclass Child3 page\u003c/h5\u003e\n      count: {store?.count} \u003cbr /\u003e\n      double: {store?.double}\n      \u003cbr /\u003e\n      \u003cbutton onClick={() =\u003e store.increase()}\u003eincrease\u003c/button\u003e\n      \u0026nbsp;\n      \u003cbutton onClick={() =\u003e store.decrease()}\u003edecrease\u003c/button\u003e\n    \u003c/div\u003e;\n  }\n}\n\nexport default observer(Child1);\n```\n\n#### 5.3 子组件为 function 组件\n\n```javascript\nimport React from \"react\";\nimport { inject, observer } from \"mobx-react\";\n\nconst Child2 = ({ store }) =\u003e {\n  return (\n    \u003cdiv\u003e\n      \u003ch2\u003efunction Child2 page\u003c/h2\u003e\n      count: {store?.count} \u003cbr /\u003e\n      double: {store?.double}\n      \u003cbr /\u003e\n      \u003cbutton onClick={() =\u003e store.increase()}\u003eincrease\u003c/button\u003e\n      \u0026nbsp;\n      \u003cbutton onClick={() =\u003e store.decrease()}\u003edecrease\u003c/button\u003e\n    \u003c/div\u003e\n  );\n};\n\nexport default inject(\"store\")(observer(Child2));\n```\n### 6. 参考资料\n1. [MobX 上手指南，写 Vue 的感觉？](https://mp.weixin.qq.com/s/AsH0nRYr3hDF2Zr4_KQOCA)\n2. [mobx-react-lite 基于 React Hook API 轻量级状态管理](https://blog.csdn.net/roamingcode/article/details/95069891)\n3. [初探mobx-react-lite](https://mu-xue.github.io/2019/08/11/front/mobx-react-lite/)\n4. [mobx-npm](https://www.npmjs.com/package/mobx)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsrect%2Fmobx-demo","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsrect%2Fmobx-demo","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsrect%2Fmobx-demo/lists"}