mobx学习笔记

本文详细介绍了JavaScript的装饰器概念及其在类和类成员修饰中的应用,包括日志记录、只读属性和参数验证。同时,文章讲解了MobX的基础语法,如可观察数据、计算属性、自动运行的函数以及如何在React中使用MobX进行状态管理。通过实例展示了如何创建和使用可观察对象,并在React组件中应用 MobX 的 observer 和 Provider 组件实现数据响应式更新。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、相关知识补充
1、什么是decorator
  • decorator是在声明阶段实现类和类成员注解的一种语法。
2、decorator修饰类

decorator有一个参数target,代表被修饰的类。例如:在调用add方法前后打印东西,可以写一个类修饰器。

function log(target){
    const desc=Object.getOwnPropertyDescriptors(target.prototype);// 获取自身的所有属性描述,背后的赋值方法或者取值方法一同拷贝过来。转成对象方便后边遍历。
    for(const key of Object.keys(desc)){
      if(key==='constructor'){
        continue;
      }
      const func=desc[key].value;
      if('function'===typeof func){
        Object.defineProperty(target.prototype, key, { // 改写add方法
          value(...arg){
            console.log(key, '之前');
            const res=func.apply(this, arg);
            console.log(key, '之后');
            return res;
          }
        })
      }
    }
  }
  @log
  class Parent{
    constructor(){
      this.pi=3.1415926;
    }
    add(...numbers){
      return numbers.reduce((total, num)=>total+num);
    }
  }

对类成员的修饰,修饰基本类型。

function myreadonly(target, key, descriptor){
    // target 修饰的目标对象
  // name 方法名
  // descriptor对象值如下
  // {
  //   value: specifiedFunction,
  //   enumerable: false,
  //   configurable: true,
  //   writable: true
  // };
    descriptor.writable=false;//不允许修改,修改就会报错
  }
  class Parent{
    constructor(){
      @readonly this.pi=3.1415926;
    }
    add(...numbers){
      return numbers.reduce((total, num)=>total+num);
    }
  }

修饰方法,假如,检验输入值类型为数值

function validate(target, key, descriptor){
    const func=descriptor.value;
    descriptor.value=function(...arg){
      for(let num of arg){
        if(typeof num!=='number'){
          throw Error(`${num} is not a number`);
        }
      }
      return func.apply(this, arg);
    }
  }
  class Parent{
    @validate
    add(...numbers){
      return numbers.reduce((total, num)=>total+num);
    }
  }
二、mobx基础语法
1、可观察数据 observable

对于基本数据类型需要使用observable.box包裹来将数据变成可观察对象,其他数据类型使用observable包裹转成可观察对象。

(1)、数组
import {observable, isObservableArray} from 'mobx'
const arr=observable([1, 2, 3]);
console.log(arr);//Proxy {0: 1, 1: 2, 2: 3, Symbol(mobx administration): ObservableArrayAdministration}
console.log(arr[0]);// 1
console.log(isObservableArray(arr));// true

仍然可以使用下标来访问数组成员。类型判断需要使用isObservableArray来判断是不是数组。

  • push和pop方法也可以使用。
  • 不要越界访问数组,会警告。
  • 可以使用for, forEach遍历数组。
(2)、对象
const obj=observable({name: 'ling', age: 16});
console.log(obj);// Proxy {Symbol(mobx administration): ObservableObjectAdministration}
console.log(obj.name);// 'ling'
  • 可以直接访问对象属性。
(3)、map
  • 可以使用set设置值
  • 使用has判断存在,get获取值, delete删除值。
(4)、基本数据类型

number,boolean, string都可以使用

const num=observable.box(20);
console.log(num);// ObservableValue {name_: "ObservableValue@3", isPendingUnobservation_: false, isBeingObserved_: false, observers_: Set(0), diffValue_: 0, …}
num.set(9);
console.log(num.get()); // 9
  • 被转换可观察对象,想要获取原始值,调用get方法。
  • 修改原始值使用set方法。
2、观察数据变化的方式
(1)、computed

将其他可观察数据,计算后输出新的可观察数据。对于其他数据来说就是对可观察数据造成反应。对自己来说就是可观察数据。

可以将多个可观察数据组合成一个可观察数据。

class Store{
    @observable name='ling';
    @observable boolean=true;
    @observable age=19;
}
const stores=new Store();
const foo=computed(function(){
	return stores.name+stores.age;
});
foo.observe_(function(change){ // 查看computed做出变化。
	console.log(change, '改变');
})
console.log(foo.age=20); //修改可观察对象
console.log(foo, '结果', foo.get());

当computed作为类成员修饰时候,返回计算后的值,因此,使用收到局限性。

class Store{
    @observable name='ling';
    @observable boolean=true;
    @observable age=19;
    @computed get mix(){
      return stores.name+stores.age;
    }
  }
  const stores=new Store();
  console.log(stores.mix);// ling19
(2)、autorun

修改autorun中引用的可观察数据,就会触发autorun运行。autorun加载时候会执行一次,好知道那些被引用了。

class Store{
    @observable name='ling';
    @observable boolean=true;
    @observable age=19;
  }
  const stores=new Store();
  autorun(()=>{
    console.log(stores.name, stores.age);
  });
  stores.name='ge';
  stores.age=29;

条件成立才触发,需要自己判断。

(3)、when

有两个参数,第一个是返回布尔值,第二个是第一个可观察对象为true执行代码。

class Store {
    @observable name = "ling";
    @observable boolean = true;
    @observable age = 19;
  }
  const stores = new Store();
  when(
    () => stores.boolean,
    () => console.log("boolean is a true")
  );
(4)、reaction

当数据变化后才触发更新

class Store {
    @observable name = "ling";
    @observable boolean = true;
    @observable age = 19;
  }
  const stores = new Store();
  reaction(()=>[stores.name, stores.age], (data)=>console.log(data));
  stores.name="lingge";
(5)、action

每次修改都会触发更新,这样性能不太好,不利于使用。因此,使用action将每次更新合并执行。

class Store {
    @observable name = "ling";
    @observable boolean = true;
    @observable age = 19;
    @action
    change(){
      this.name='ge';
      this.age=20;
    }
}
const stores = new Store();
reaction(()=>[stores.name, stores.age], (data)=>console.log(data.name, data.age));
stores.change();

也可以使用bund全局使用上下问,传递函数在其他地方使用。

class Store {
    @observable name = "ling";
    @observable boolean = true;
    @observable age = 19;
    @action.bound
    change(){
      this.name='ge';
      this.age=20;
    }
  }
  const stores = new Store();
  reaction(()=>[stores.name, stores.age], (data)=>console.log(data.name, data.age));
  const bar=stores.bar;
  bar();

action建议使用,性能较好

三、mobx在react中使用
1、组件修饰器

为了让mobx观察数据变化更新视图,要给使用到可观察对象变化组件加类修饰。

import { observer } from "mobx-react";
@observer
class Parent extends Component{
    render(){
        return (<div>123</div>)
    }
}

对于函数编程,使用observer将hooks组件包裹起来。

import { observable } from "mobx";
import { observer } from "mobx-react";
appState=observable({ timer: 0 });
export default App=observer(({store})=>(<div>我是内容</div>))
ReactDOM.render(<App store={appState} />, root);
四、类组件中初探使用mobx完成数据管理
1、创建可观察数据store
import {observable, computed, action} from 'mobx';
class Store{
  @observable list=[];
  @observable id=20;
  @computed get getList(){
    return this.list;
  }
  @action addList(item){
    this.list.push(item);
  };
  @action addId(item){
    this.id=item;
  }
}
const store=new Store();
export default store;
2、创建父组件
import { Component } from "react";
import { Provider, observer } from "mobx-react";

import "./App.css";
import store from './store/index';
import MyHeader from './components/MyHeader';
import Footer from './components/Footer';

@observer
class App extends Component {
  render() {
    return (
      <Provider className="App" store={store}>
        <MyHeader />
        <Footer />
      </Provider>
    );
  }
}

export default App;
3、footer组件
import { Component, React } from "react";
import { inject, observer } from "mobx-react";

@inject("store")
@observer
class MyHeader extends Component {
  render() {
    return (
      <div>
        {this.props.store.list &&
          this.props.store.list.map((item) => {
            return (
              <div>
                <span>{item.name}</span>
                <span>{item.age}</span>
              </div>
            );
          })}
      </div>
    );
  }
}
export default MyHeader;
4、header组件
import { Component } from "react";

import { inject, observer } from "mobx-react";

@inject("store")
@observer
class MyHeader extends Component {
  constructor(props){
    super(props);
    this.handleChange=this.handleChange.bind(this);
  }
  handleChange(){
    this.props.store.addList({name: 'linge', age: this.props.store.id});
    this.props.store.addId(this.props.store.id+1);
  }
  render() {
    return (
      <div>
        <button onClick={this.handleChange}>点击</button>
      </div>
    );
  }
}
export default MyHeader;
5、目录结构

在这里插入图片描述
注意:由于我用的是react17,因此,无需引入React

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值