redux的竞品 ,
EventEmitter
http://www.runoob.com/nodejs/nodejs-event.html

mobx的官方网站
https://mobx.js.org/index.html

dva的官方网站
https://dvajs.com/guide/concepts.html#%E6%95%B0%E6%8D%AE%E6%B5%81%E5%90%91

mobx 5.9.4

23天前出版,2019-04-22日的23天前。
CDN

  1. npm i mobx mobx-react --save
  2. npm install mobx-react --save
  3. ESNext装饰器(可选)
  4. CDN
  5. https://unpkg.com/mobx/lib/mobx.umd.js
  6. https://cdnjs.com/libraries/mobx

介绍 反应式虚拟依赖状态图 mobx

MobX 是一个经过战火洗礼的库,它通过透明的函数响应式编程(transparently applying functional reactive programming - TFRP)使得状态管理变得简单和可扩展。MobX背后的哲学很简单:
任何源自应用状态的东西都应该自动地获得。
其中包括UI、数据序列化、服务器通讯,等等。
要想使用 @observable 装饰器,首先要确保 在你的编译器(babel 或者 typescript)中 装饰器是启用的
image.png

定义observable, observer 和 action

observable 美 [əbˈzɜ:rvəbl] 可观察的
observer 美 [əbˈzɜ:rvə(r)] 观察者
actions 活动
computed 美[‘kɒmpət] 计算属性
modify [ˈmɑ:dɪfaɪ] 修改,被修饰的

mobx的工作步骤

一,定义你的状态,并使其可观察
二,创建一个响应更改的视图
三,更改状态
https://egghead.io/courses/manage-complex-state-in-react-apps-with-mobx

image.png

视频第一课代码

  1. const { observable } = mobx;
  2. const { boserver } = mobxReact;
  3. cosnt { Component } = React;
  4. @observer class Counter extends Component {
  5. @observable count = 0;
  6. render() {
  7. return (<div>
  8. Counter: {this.count} <br/>
  9. <button onClick={this.handleInc}> + </button>
  10. <button onClick={this.handleDec}> - </button>
  11. </div>)
  12. }
  13. handleInc = () => {
  14. this.count++;
  15. }
  16. handleDec = () => {
  17. this.count--;
  18. }
  19. }
  20. ReactDom.render(
  21. <Counter />,
  22. document.getElementById('app')
  23. );
  1. const { observable } = mobx;
  2. const { boserver } = mobxReact;
  3. cosnt { Component } = React;
  4. const appState = observable({
  5. count: 0,
  6. });
  7. appState.increment = function () {
  8. this.count++;
  9. }
  10. appState.decrement = function () {
  11. this.count--;
  12. }
  13. @observer class Counter extends Component {
  14. render() {
  15. return (<div>
  16. Counter: {this.props.store.count} <br/>
  17. Counter: {appState.count} <br/>
  18. <button onClick={this.handleInc}> + </button>
  19. <button onClick={this.handleDec}> - </button>
  20. </div>)
  21. }
  22. handleInc = () => {
  23. this.props.store.increment();
  24. appState.increment();
  25. }
  26. handleDec = () => {
  27. this.props.store.decrement();
  28. appState.decrement();
  29. }
  30. }
  31. ReactDom.render(
  32. <Counter store={appState} />,
  33. document.getElementById('app')
  34. );

视频第二课的代码

  1. const { observable } = mobx;
  2. const { boserver } = mobxReact;
  3. cosnt { Component } = React;
  4. const DevTools = mobxDevtools.default;
  5. const appState = observable({
  6. count: 0,
  7. });
  8. appState.increment = function () {
  9. this.count++;
  10. }
  11. appState.decrement = function () {
  12. this.count--;
  13. }
  14. @observer class Counter extends Component {
  15. render() {
  16. return (<div>
  17. <DevTools />
  18. Counter: {this.props.store.count} <br/>
  19. Counter: {appState.count} <br/>
  20. <button onClick={this.handleInc}> + </button>
  21. <button onClick={this.handleDec}> - </button>
  22. </div>)
  23. }
  24. handleInc = () => {
  25. this.props.store.increment();
  26. appState.increment();
  27. }
  28. handleDec = () => {
  29. this.props.store.decrement();
  30. appState.decrement();
  31. }
  32. }
  33. ReactDom.render(
  34. <Counter store={appState} />,
  35. document.getElementById('app')
  36. );

视频第三课的代码

  1. const { observable, computed } = mobx;
  2. const { observer } = mobxReact;
  3. const { Component } = React;
  4. const DevTools = mobxDevtools.default;
  5. const t = new class Temperature {
  6. @observable unit = 'C';
  7. @observable temperatureCelsius = 25;
  8. @computed get temperatureKelvin(){
  9. console.log('calculating Kelvin');
  10. return this.temperatureCelsius * (9/5) + 32
  11. }
  12. @computed get temperatureFahrenthit() {
  13. console.log('calculating Fahrenheit');
  14. return this.temperatureCelsius + 273.15
  15. }
  16. @computed get temperature {
  17. console.log('calculating temperature')
  18. switch(this.unit) {
  19. case 'K': return this.temperatureKelvin + '°K';
  20. case 'F': return this.temperatureFahrenthit + '°F';
  21. case 'C': return this.temperatureCelsius + '°C';
  22. defalut: ;
  23. }
  24. }
  25. }
  26. // t.unit = 'K';
  27. // t.temperature
  28. // 'calculating temperature'
  29. // 'calculating Kelvin'
  30. // '68°K'
  31. // t.unit = 'F';
  32. // t.temperature
  33. // 'calculating temperature'
  34. // 'calculating Fahrenheit'
  35. // '293.15°F'
  36. const App = observer(({temperature}) => (<div>
  37. {temperature.temperature}
  38. <DevTools />
  39. </div>))
  40. ReactDom.reder(
  41. <App temperature={t} />,
  42. document.getElementById('app')
  43. )

视频第四课与第五课的代码,@active

  1. const { observable, computed } = mobx;
  2. const { observer } = mobxReact;
  3. const { Component } = React;
  4. const DevTools = mobxDevtools.default;
  5. const t = new class Temperature {
  6. /*
  7. @observable unit = 'C';
  8. @observable temperatureCelsius = 25;
  9. */
  10. constructor() {
  11. extendsObservable(this, {
  12. unit: 'C',
  13. temperatureCelsius: 25
  14. })
  15. }
  16. @computed get temperatureKelvin(){
  17. console.log('calculating Kelvin');
  18. return this.temperatureCelsius * (9/5) + 32
  19. }
  20. @computed get temperatureFahrenthit() {
  21. console.log('calculating Fahrenheit');
  22. return this.temperatureCelsius + 273.15
  23. }
  24. @computed get temperature {
  25. console.log('calculating temperature')
  26. switch(this.unit) {
  27. case 'K': return this.temperatureKelvin + '°K';
  28. case 'F': return this.temperatureFahrenthit + '°F';
  29. case 'C': return this.temperatureCelsius + '°C';
  30. defalut: ;
  31. }
  32. }
  33. @action setUnit(newUnit){
  34. this.unit = newUnit;
  35. }
  36. @action setCelsius(newCelsius) {
  37. this.temperatureCelsius = newCelsius;
  38. }
  39. }
  40. const App = observer(({temperature}) => (<div>{temperature.temperature}<DevTools /></div>))
  41. ReactDom.reder(
  42. <App temperature={t} />,
  43. document.getElementById('app')
  44. )
  1. const { observable, computed } = mobx;
  2. const { observer } = mobxReact;
  3. const { Component } = React;
  4. const DevTools = mobxDevtools.default;
  5. const t = observable({
  6. unit: 'C',
  7. temperatureCelsius: 25,
  8. temperatureKelvin: function(){
  9. console.log('calculating Kelvin');
  10. return this.temperatureCelsius * (9/5) + 32
  11. },
  12. temperatureFahrenthit: function() {
  13. console.log('calculating Fahrenheit');
  14. return this.temperatureCelsius + 273.15
  15. },
  16. temperature: function() {
  17. console.log('calculating temperature')
  18. switch(this.unit) {
  19. case 'K': return this.temperatureKelvin + '°K';
  20. case 'F': return this.temperatureFahrenthit + '°F';
  21. case 'C': return this.temperatureCelsius + '°C';
  22. defalut: ;
  23. }
  24. }
  25. });
  26. // t.unit = 'K';
  27. // t.temperature
  28. // 'calculating temperature'
  29. // 'calculating Kelvin'
  30. // '68°K'
  31. // t.unit = 'F';
  32. // t.temperature
  33. // 'calculating temperature'
  34. // 'calculating Fahrenheit'
  35. // '293.15°F'
  36. const App = observer(({temperature}) => (<div>{temperature.temperature}<DevTools /></div>))
  37. ReactDom.reder(
  38. <App temperature={t} />,
  39. document.getElementById('app')
  40. )
  1. const { observable, computed } = mobx;
  2. const { observer } = mobxReact;
  3. const { Component } = React;
  4. const DevTools = mobxDevtools.default;
  5. class Temperature {
  6. id = Math.random();
  7. @observable unit = 'C';
  8. @observable temperatureCelsius = 25;
  9. @computed get temperatureKelvin(){
  10. console.log('calculating Kelvin');
  11. return this.temperatureCelsius * (9/5) + 32
  12. }
  13. @computed get temperatureFahrenthit() {
  14. console.log('calculating Fahrenheit');
  15. return this.temperatureCelsius + 273.15
  16. }
  17. @computed get temperature {
  18. console.log('calculating temperature')
  19. switch(this.unit) {
  20. case 'K': return this.temperatureKelvin + '°K';
  21. case 'F': return this.temperatureFahrenthit + '°F';
  22. case 'C': return this.temperatureCelsius + '°C';
  23. defalut: ;
  24. }
  25. }
  26. @action setUnit(newUnit){
  27. this.unit = newUnit;
  28. }
  29. @action setCelsius(newCelsius) {
  30. this.temperatureCelsius = newCelsius;
  31. }
  32. @action("Update temperature and unit")
  33. setTemperatureOrUnit(temperature, unit){
  34. this.setUnit(unit);
  35. this.setsetCelsius(temperature);
  36. }
  37. }
  38. /*
  39. const temps = observable([]);
  40. temps.push(new Temperature());
  41. */
  42. const temps = observable(asMap({
  43. "Amsterdam": new Temperature(),
  44. "Rome": new Temperature()
  45. }));
  46. const App = observer(({temperature}) => (<div>
  47. /*
  48. {temperature.map(t => <div key={t.id}>{t.temperature}</div>)}
  49. */
  50. {temperature.entries().map(([city, t])=>{
  51. return <div key={t.id}>{city}: {t.temperature}</div>
  52. })}
  53. <DevTools /></div>))
  54. ReactDom.reder(
  55. <App temperature={temps} />,
  56. document.getElementById('app')
  57. )
  58. /*
  59. // temps[0].unit = 'K';
  60. // temps.push(new Temperature());
  61. // temps.splice(o, 1);
  62. // temps[1] = new Temperature(); 此无效
  63. // Array.isArray(temps); // false
  64. // Array.isArray(temps.slice()); // true
  65. // Array.isArray(temps.toJS()); // true
  66. */
  67. // temps.get("Amsterdam").unit = 'K';
  68. // temps.set("Tel Aviv", new Temperature());
  1. const boxed = observable(42);
  2. boxed.get(); // 42
  3. boxed.set(52) // undefined
  4. boxed.get(); // 52

image.png

视频第六课 observer

  1. const { observable, computed } = mobx;
  2. const { observer } = mobxReact;
  3. const { Component } = React;
  4. const DevTools = mobxDevtools.default;
  5. class Temperature {
  6. id = Math.random();
  7. @observable unit = 'C';
  8. @observable temperatureCelsius = 25;
  9. @computed get temperatureKelvin(){
  10. console.log('calculating Kelvin');
  11. return this.temperatureCelsius * (9/5) + 32
  12. }
  13. @computed get temperatureFahrenthit() {
  14. console.log('calculating Fahrenheit');
  15. return this.temperatureCelsius + 273.15
  16. }
  17. @computed get temperature {
  18. console.log('calculating temperature')
  19. switch(this.unit) {
  20. case 'K': return this.temperatureKelvin + '°K';
  21. case 'F': return this.temperatureFahrenthit + '°F';
  22. case 'C': return this.temperatureCelsius + '°C';
  23. defalut: ;
  24. }
  25. }
  26. @action setUnit(newUnit){
  27. this.unit = newUnit;
  28. }
  29. @action setCelsius(newCelsius) {
  30. this.temperatureCelsius = newCelsius;
  31. }
  32. @action("Update temperature and unit")
  33. setTemperatureOrUnit(temperature, unit){
  34. this.setUnit(unit);
  35. this.setsetCelsius(temperature);
  36. }
  37. @action inc() {
  38. this.setCelsius(this.temperatureCelsius + 1)
  39. }
  40. }
  41. const temps = observable(asMap({
  42. "Amsterdam": new Temperature(),
  43. "Rome": new Temperature()
  44. }));
  45. const App = observer(({temperature}) => (<div>
  46. {temperature.entries().map(([city, t])=>{
  47. return <TView city={city} temperature={t} />
  48. })}
  49. @observer class TView extends Component {
  50. render(){
  51. const t = this.props.temperature;
  52. const city = this.props.city;
  53. return(<li onClick={this.onTemperatureClick}>{city}: {t.temperature}</li>)
  54. }
  55. @active onTemperatureClick(){ // 这里不能使用箭头函数
  56. this.props.temperature.inc();
  57. }
  58. }
  59. <DevTools /></div>))
  60. ReactDom.reder(
  61. <App temperature={temps} />,
  62. document.getElementById('app')
  63. )

视频第七课 ,异步的action修改状态