最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • mobx、mobx-react和mobx-react-lite新手入门

    正文概述 掘金(sRect)   2021-03-31   2127

    1. 写在前面

    本文会介绍mobxmobx-reactmobx-react-lite的基本使用,还有配合react context api的使用,都是api的入门使用,不涉及源码剖析。

    2. 什么是Mobx?

    1. Simple, scalable state management
    2. MobX is a battle tested library that makes state management simple and scalable by transparently applying functional reactive programming (TFRP)

    Mobx是简单、可扩展的状态管理库。是经过战斗洗礼的库,通过透明的函数响应式编程使状态管理变得更加简单且可扩展。说明Mobx足够可靠,可放心在项目中使用。

    mobx、mobx-react和mobx-react-lite新手入门

    上图所示,Mobx是通过event事件调用action,修改observal state数据,进而触发computed,使其自动更新数据,Reactions是对state的改变做出的反应,以此更新视图,这是Mobx的核心所在

    3. mobx的使用

    mobx 为 6.x 版本,常用api的使用

    3.1 使用makeObservable

    import {makeObservable,observable,action,computed,autorun,reaction,when} from "mobx";
    // 创建store
    const store = makeObservable({
        count:1,
        get double(){return this.count * 2;},
        // 定义action
        increment(){this.count += 1;},
        decrement(){this.count -= 1;},
    },{
        count: observable,//需要响应的属性
        double: computed,//计算属性
        increment: action,//action
        decrement: action,
    });
    class MobxDemo {
      handleRefresh(){
        this.container.innerHTML=`
          count: ${store.count}
          double count: ${store.double}
        `;
      }
      init() {
        this.handleRefresh();
        this.increaseBtn.addEventListener("click",()=>{store.increment();});
        this.decreaseBtn.addEventListener("click",()=>{store.decrement();});
        // autorun类似于react hooks中的useEffect
        // 当observable响应属性被更新时,autorun立即被调用一次
        autorun(()=>{this.handleRefresh();});
        // 类似Vue中的watch观察
        reaction(
          ()=>store.count, // 指定观察count属性
          (currentVal, oldVal)=>{console.log(`current: ${currentVal}, old: ${oldVal}`);}
        );
        // 条件响应
        when(
          ()=>store.count < 0,
          ()=>{console.log("...");}
        );
      }
    }
    const mobxDemo = new MobxDemo();
    mobxDemo.init();

    3.2 使用makeAutoObservable

    相比makeObservable,makeAutoObservable就简化多了,无需再手动指定observable、action、computed

    import {makeAutoObservable,autorun,runInAction} from "mobx";
    // 直接使用makeAutoObservable
    const store = makeAutoObservable({
      count: 1,
      get double(){return this.count*2;},
      increment(){this.count+=1;},
      decrement(){this.count-=1;},
      // 在 MobX 中,不管是同步还是异步操作,都可以放到 action 中,
      // 只是异步操作在修改属性时,需要将赋值操作放到 runInAction 中。
      async asyncDecreament() {
        // 模拟ajax获取数据
        const count = await new Promise((resolve)=>{
          setTimeout(()=>resolve(1), 50);
        });
        // 获取数据后,将赋值操作放到 runInAction 中
        runInAction(()=>{this.count -= count;});
      },
    });

    3.3 使用 6.x 版本之前的 decorator 装饰器写法

    import {observable,action,computed} from "mobx";
    class Store {
      @observable count=0;
      constructor(){makeObservable(this);}
      @computed get double(){return this.count * 2;}
      @action increment(){this.count++;}
      @action decrement(){this.count--;}
    }
    const store = new Store();

    4. mobx-react-lite的使用

    mobx-react-litemobx-react的轻量化版本,在mobx-react@6版本中已经包含了mobx-react-lite,但是如果只在函数式组件中使用,推荐使用轻量化的mobx-react-lite

    4.1 父组件使用useLocalObservable创建store

    import React,{createContext} from "react";
    import {observer,useLocalObservable} from "mobx-react-lite";
    import Child1 from "@/component/Child1";
    import Child2 from "@/component/Child2";
    import Child3 from "@/component/Child3";

    export const Context = createContext(null);

    const Parent=()=>{
      // 'useLocalStore' is deprecated, use 'useLocalObservable' instead.
      const storeContext = useLocalObservable(()=>({
        count: 1,
        get double(){return this.count*2;},
        increase(){this.count+=1;},
        decrease(){this.count-=1;},
      }));
      return (
        <Context.Provider value={storeContext}>
          <Child1 />
          <Child2 />
          <Child3 />
        </Context.Provider>
      );
    };
    export default observer(Parent);

    4.2 子组建为function组件(使用Context)

    import React, {useContext,useEffect} from "react";
    import {observer} from "mobx-react-lite";
    import {toJS,reaction,when} from "mobx";
    import {Context} from "@/App";
    const Child1=()=>{
      const store=useContext(Context);
      useEffect(()=>{
        console.log("store:", toJS(store));
        reaction(
          ()=>store.count,
          (cur, pre)=>{console.log(`cur: ${cur}, pre: ${pre}`);}
        );
        when(
          ()=>store.count < 0,
          ()=>{console.log("...");}
        );
      }, [store]);
      // [mobx-react-lite] 'useObserver(fn)' is deprecated
      // Use `<Observer>{fn}</Observer>`instead, or wrap the entire component in `observer`
      return(
        <div>
          count: {store?.count}|double:{store?.double}    
          <button onClick={()=>store.increase()}>increase</button>
          <button onClick={()=>store.decrease()}>decrease</button>
        </div>
      );
    };
    export default observer(Child1);

    4.3 子组建为function组件(不使用Context)

    不使用 Context,就要用到mobx-react,看 5.3 部分

    4.4 子组件为 class 组件

    通过Context.Consumer组件获取到store

    import React,{Component} from "react";
    import {Observer} from "mobx-react-lite";
    import {Context} from "@/App";
    class Child3 extends Component {
      render(){
        return(
          <Context.Consumer>
            {(store)=>(
              <div>
                <Observer>{()=><div>count:{store?.count}</div>}</Observer>
                <button onClick={()=>store.increase()}>increase</button>
                <button onClick={()=>store.decrease()}>decrease</button>
              <div/>
            )}
          </Context.Consumer>
        );
      }
    }
    export default Child3;

    5. mobx-react的使用

    5.1 父组件用mobx-react提供的Provider组件向下传递store

    import React from "react";
    import {Provider} from "mobx-react";
    import {useLocalObservable} from "mobx-react-lite";
    import Child1 from "@/component/Child1";
    import Child2 from "@/component/Child2";
    const Parent=()=>{
      // 也可以使用mobx创建一个store
      const storeContext = useLocalObservable(()=>({
        count:1,
        get double(){return this.count*2;},
        increase(){this.count+=1;},
        decrease(){this.count-=1;},
      }));
      return (
        <Provider store={storeContext}>
          <Child1 />
          <Child2 />
        </Provider>
      );
    };
    export default observer(Parent);

    5.2 子组件为 class 组件

    import React from "react";
    import {observer,inject} from "mobx-react";
    @inject("store")
    @observer
    class Child1 extends React.Component {
      render()(
        <>
          count:{store?.count}|double:{store?.double}
          <button onClick={()=>store.increase()}>increase</button>
          <button onClick={()=>store.decrease()}>decrease</button>
        </>
      )
    }
    export default observer(Child1);

    5.3 子组件为 function 组件

    import React from "react";
    import {inject,observer} from "mobx-react";
    const Child2=({store})=>{
      return(
        <>
          count:{store?.count}|double:{store?.double}
          <button onClick={()=>store.increase()}>increase</button>
          <button onClick={()=>store.decrease()}>decrease</button>
        </>
      );
    };
    export default inject("store")(observer(Child2));

    6. 参考资料

    1. MobX 上手指南,写 Vue 的感觉?
    2. mobx-react-lite 基于 React Hook API 轻量级状态管理
    3. 初探mobx-react-lite
    4. mobx-npm

    起源地下载网 » mobx、mobx-react和mobx-react-lite新手入门

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    你写代码的一行到头的???
    回复(0)

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元