1.autorun

当你想创建一个响应式函数,而该函数本身永远不会有观察者时,可以使用 mobx.autorun。 这通常是当你需要从反应式代码桥接到命令式代码的情况,例如打印日志、持久化或者更新UI的代码。 当使用 autorun 时,所提供的函数总是立即被触发一次,然后每次它的依赖关系改变时会再次被触发。 相比之下,computed(function) 创建的函数只有当它有自己的观察者时才会重新计算,否则它的值会被认为是不相关的。 经验法则:如果你有一个函数应该自动运行,但不会产生一个新的值,请使用autorun。 其余情况都应该使用 computed。 Autoruns 是关于 启动效果 (initiating effects) 的 ,而不是产生新的值。 如果字符串作为第一个参数传递给 autorun ,它将被用作调试名。

  1. //autorun自动执行一次
  2. //然后当内部所依赖的被观测的数据发生改变的时候重新执行
  3. autorun(() => {
  4. //当store.count发生改变。他会自动触发,需要给数据成员加上@observable
  5. console.log( store.count, "fffrrrf");
  6. console.log( store.num1, "num1ffrrrf");
  7. console.log( store.num2, "num2ffrrrf");
  8. });

2.when

when 观察并运行给定的 predicate,直到返回true。 一旦返回 true,给定的 effect 就会被执行,然后 autorunner(自动运行程序) 会被清理。 该函数返回一个清理器以提前取消自动运行程序

  1. //当count大于等于100的时候,只执行一次自定义逻辑
  2. //如果条件满足一上来就会执行,只会执行一次
  3. when(
  4. ()=>{
  5. return store.count>=100
  6. },
  7. ()=>{
  8. console.log('when=>',store.count);
  9. }
  10. )

3.reaction

autorun 的变种,对于如何追踪 observable 赋予了更细粒度的控制。 它接收两个函数参数,第一个(数据 函数)是用来追踪并返回数据作为第二个函数(效果 函数)的输入。 不同于 autorun 的是当创建时效果 函数不会直接运行,只有在数据表达式首次返回一个新值后才会运行。 在执行 效果 函数时访问的任何 observable 都不会被追踪。 reaction 返回一个清理函数。 传入 reaction 的第二个函数(副作用函数)当调用时会接收两个参数。 第一个参数是由 data 函数返回的值。 第二个参数是当前的 reaction,可以用来在执行期间清理 reaction 值得注意的是 效果 函数对数据函数中访问的数据作出反应,这可能会比实际在效果函数使用的数据要少。 此外,效果 函数只会在表达式返回的数据发生更改时触发。 换句话说: reaction需要你生产 效果 函数中所需要的东西。

  1. //可以频繁触发
  2. reaction(
  3. ()=>{
  4. //做业务操作,把结果给第二个函数
  5. return store.count
  6. },
  7. //data是上个函数的结果
  8. (data,reaction)=>{
  9. console.log(data);
  10. console.log(reaction);
  11. //手动停止reacttion中数据的更新
  12. reaction.dispose()
  13. }
  14. )

代码片段

  1. import React from "react";
  2. import ReactDOM from "react-dom";
  3. import {
  4. observable,
  5. action,
  6. makeAutoObservable,
  7. autorun,
  8. configure,
  9. runInAction,
  10. when,
  11. reaction
  12. } from "mobx";
  13. import { observer } from "mobx-react";
  14. configure({
  15. enforceActions: "observed",
  16. });
  17. //初始化mobx仓库
  18. class Store {
  19. @observable count = 0;
  20. @observable num1 = 0;
  21. @observable num2 = 0;
  22. //一定要加这一行
  23. constructor() {
  24. makeAutoObservable(this);
  25. }
  26. @action
  27. increment = () => {
  28. this.count++;
  29. };
  30. //1.定义一个同步函数用于修改,在异步函数中调用
  31. @action.bound
  32. changeCountAsync() {
  33. setTimeout(() => {
  34. this.shngecount()
  35. }, 1000);
  36. }
  37. @action.bound
  38. shngecount(){
  39. this.count=100
  40. }
  41. //2.在异步函数中调用action函数,第一参数是修改函数的名称
  42. @action.bound
  43. changenum1Async() {
  44. setTimeout(() => {
  45. action('changnum1',()=>{
  46. console.log(this);
  47. this.num1=1002
  48. })()
  49. }, 1000);
  50. }
  51. //3.使用runInAction
  52. @action.bound
  53. changenum2Async() {
  54. setTimeout(() => {
  55. runInAction(()=>{
  56. console.log(this);
  57. this.num2=1003
  58. })
  59. }, 1000);
  60. }
  61. }
  62. const store = new Store();;
  63. //autorun自动执行一次
  64. //然后当内部所依赖的被观测的数据发生改变的时候重新执行
  65. autorun(() => {
  66. //当store.count发生改变。他会自动触发,需要给数据成员加上@observable
  67. console.log( store.count, "fffrrrf");
  68. console.log( store.num1, "num1ffrrrf");
  69. console.log( store.num2, "num2ffrrrf");
  70. });
  71. //当count大于等于100的时候,只执行一次自定义逻辑
  72. when(
  73. ()=>{
  74. return store.count>=100
  75. },
  76. ()=>{
  77. console.log('when=>',store.count);
  78. }
  79. )
  80. reaction(
  81. ()=>{
  82. //做业务操作,把结果给第二个函数
  83. return store.count
  84. },
  85. //data是上个函数的结果
  86. (data,reaction)=>{
  87. console.log(data);
  88. console.log(reaction);
  89. //手动停止reacttion中数据的更新
  90. // reaction.dispose()
  91. }
  92. )
  93. //函数调用
  94. store.changeCountAsync()
  95. store.changenum1Async()
  96. store.changenum2Async()
  97. @observer
  98. class App extends React.Component {
  99. render() {
  100. const { store } = this.props;
  101. return (
  102. <div>
  103. <h1>我是一个仓库</h1>
  104. <h2>{store.count}</h2>
  105. <button onClick={store.increment}>增加</button>
  106. </div>
  107. );
  108. }
  109. }
  110. ReactDOM.render(<App store={new Store()} />, document.getElementById("root"));