前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >🚀🚀🚀初识mobx,以及mobx-react使用

🚀🚀🚀初识mobx,以及mobx-react使用

原创
作者头像
萌萌哒将军
发布2024-07-14 21:54:18
970
发布2024-07-14 21:54:18
举报
文章被收录于专栏:前端框架

六月底因为前司经济性裁员,10天内疯狂面试拿到好几个offer(外包字节、外包学而思和一些不知名的小公司),果然是树挪死人挪活,最后选择了还不错的公司,新公司主要是做机器人软件和云端管理软件的,前景还算可以。随后会整理最近的面经(已经在整理中了,是React方向),敬请期待。

新公司主要的技术栈是React+Typescript+carbonDesign+Mobx+GraphGL+Jest+nuxtjs,相较于上司,有很多需要扩展的知识点。

今天主要介绍下Mobx。

欢迎关注我的公众号:萌萌哒草头将军

Mobx简介

Mobx是响应式状态管理库,无关任何前端框架。现在已经发布到Mobx6了。在Mobx5之前,响应式原理是基于Object.defineProperty的,可以向下兼容到ES5浏览器,而从Mobx5开始使用proxy特性支持响应式,最低支持ES6浏览器。

相较于Redux,Mobx只强调下面三个概念

  • State(状态)
  • Actions(动作)
  • Derivations(派生)

一句话概括:在任何事件中调用action,修改state,如果这个state是响应式的,那么会通知基于这个state派生的计算值,或者触发派生的副作用。

其中派生属性可以分为两种情况

  • 计算值(computeds):类似于React的useMemo方法和Vue的computer方法
  • 副作用(reactions):类似于React的useEffect方法和Vue的WatchEffect方法

两种写法

通过Mobx定义一个响应式的Store有很多种方法,在不同的方法中定义他们也有所不同。

1. class写法

类的写法虽然笨重,但是适合模块化开发,易于扩展和维护。

代码语言:javascript
复制
import { makeObservable, observable, action, runInAction } from "mobx";

class MyStore {
    let tableList = [];
    let condition = {
        current: 1,
        pageSize: 10,
        // ...other
    };
    
    constructer () {
        constructor(title) {
            makeObservable(this, {
                tableList: observable,
                condition: observable,
                getTableList: action,
                onConditionChangez: action
            })
        
            // 设置 reaction,当 condition 变化时自动请求 tableList 数据
            reaction(
                () => this.condition, // 监听的表达式
                (condition) => this.getTableList(condition) // 触发的副作用
            )
            // 初始化时默认请求列表数据
            this.getTableList(this.condition);
        }
        // 计算属性
        get getInBeijing() {
            return this.tableList.map(item => item.address === "beijing");
        }
        getTableList (condition) {
            fetch("/v1/table/list", {
                method: "post",
                data: condition
            }).then((res) => {
                runInAction(() => {
                    this.tableList = res.data.list;
                })
            })
        }
        onConditionChange (condition) {
            this.condition = condition;
        }
    }
}
2.直接使用接口

使用接口创建对象的写法通常和组件结合在一起使用,虽然灵活,但是由于太过零散,不易于扩展。

代码语言:javascript
复制
import { observable, action } from "mobx"

funtion App () {
    const myStore = observable({
        tableList: [],
        condition: {
            pageSize: 10,
            current: 1,
            // ...other
        },
        // 计算属性
        get getInBeijing() {
            return this.tableList.map(item => item.address === "beijing");
        }
    })
    // 副作用
    reaction(
        () => myStore.condition,
        () => getTableList()
    };

    const getTableList = action(() => {
        fetch("/v1/table/list", {
            method: "post",
            data: myStore.condition
        }).then((res) => {
            runInAction(() => {
                myStore.tableList = res.data.list;
            })
        })
    })

    const onConditionChange = action(myStore) => {
        myStore.condition = condition
    }
    
    useEffect(() => {
        myStore.getTableList(myStore.condition);
    }, [])
    
    return <>
        <Condition condition={myState.condtion} onChange={onConditionChange} />
        <Table data={myState.tableList} onPaigionChange={onConditionChange} />
    </>
 }

副作用

关于副作用,除了上面使用的reaction方法还有autorunwhen。具体的使用如下:

  • autorun:当依赖属性值的变化执行一个指定的方法,自动收集依赖
  • reaction:将第一个方法的返回值作为第二个方法的参数,然后执行第二个方法
  • when:当第一个方法的返回值为true时,执行第二个方法
代码语言:javascript
复制
reaction(
    () => this.condition, // 监听的表达式
    (condition) => this.getTableList(condition) // 触发的副作用
)

when(
    () => !this.condition,
    () => console.log("数据为空")
)
// 当when方法没有设置第二个参数时,会返回Promise对象
when(() => !this.condition).then(() => {
   console.log("数据为空");
})

autorun(() => this.getTableList(this.condition))

另外记得,这些副作用都会返回销毁监听的方法,例如,在React使用Mobx时,通常我们会在组件销毁时清除他们

代码语言:javascript
复制
useEffect(() => {
    const dispose = reaction(
        () => this.condition, // 监听的表达式
        (condition) => this.getTableList(condition) // 触发的副作用
    )
    // return () => disopose()
    return dispose
}, [])

但是在实际的开发中,我们会使用具体的和框架相关的Mobx,mobx-react、mobx-vue。这样的好处是和组件结合的更紧密,而且不用每次都指定销毁方法。

Mobx-react的一些用法

在React中使用Mobx,通常有两个包:mobx-react、mobx-react-lite

  • mobx-react:提供类组件和hook组件的一些方法
  • mobx-react-lite:仅仅提供hook租价你的一些方法

在react的写法也有很多种,下面是几种常见的写法(我们依然使用上面的MyStore类)

1.依赖注入的写法

代码语言:javascript
复制
const myStore = new Mystore()
const StoreContext = createContext(myStore);

const App = observer(() => {
    const myState = useContext(StoreContext)
    
    return <>
        <Condition condition={myState.condtion} onChange={myState.onConditionChange} />
        <Table data={myState.tableList} onPaigionChange={myState.onConditionChange} />
    </>
})

ReactDOM.render(
    <StoreContext.Provider value={myStore}>
        <App />
    </StoreContext.Provider>,
    document.body
)

2.自定义hook钩子

代码语言:javascript
复制
const App = observer(() => {
    const [state] = useState(() => new Mystore())
    
    return <>
        <Condition condition={myState.condtion} onChange={state.onConditionChange} />
        <Table data={myState.tableList} onPaigionChange={state.onConditionChange} />
    </>
})

ReactDOM.render(<App />, document.body)

3.使用useLocalObservable钩子

useLocalObservable钩子可以看作是官方的自定义hook,上面的方法等价于下面的方法

代码语言:javascript
复制
const App = observer(() => {
    const state = useLocalObservable(() => new Mystore())
    
    return <>
        <Condition condition={myState.condtion} onChange={state.onConditionChange} />
        <Table data={myState.tableList} onPaigionChange={state.onConditionChange} />
    </>
})

ReactDOM.render(<App />, document.body)

observer函数和Observer组件的使用

从上面的示例中可以看到,组件都会使用observer函数包裹了,这是当state发生变化时,mobx确保组件重新渲染了。它的原理是一个高阶组件,后续会详细说说这个高阶组件的原理。

有的时候你需要使用render api的方式渲染组件,而且需要渲染的子组件是可观察的,那么可以使用Observer组件.

代码语言:javascript
复制
const Address = observer(({address}) => <div>{address}</>)

const App = () => {
    const state = useLocalObservable(() => new Mystore())
    
    return <Observer>
        {
            () => state.getInBeijing.map(address => <Address address={address} />)
        }
    </Observer>
}

注意,如果上面的Address组件如果需要是可观察的,需要使用observer函数或者Observer组件包裹

代码语言:javascript
复制
const Address = ({address}) => <div>{address}</>

const App = () => {
    const state = useLocalObservable(() => new Mystore())
    
    return <>
        {
            () => state.getInBeijing.map(address => <Observer>
                <Address address={address} />
            </Observer>)
        }
    </>
}

注解的写法

在mobx6开始已经不建议使用注解的写法了,但是你仍然可以使用这个功能。

使用时,需要先给idea设置注解识别功能,然后配置相关的babel插件,这里不展开了,详细的内容可以看看这里

今天的学习内容就这些了,下篇文章会先将整理好的面经发布出来,然后继续分享在新公司的一些学习笔记。希望可以帮助更多的人。文章如果有错误的地方欢迎指正!

因为新公司离家更近了,每天节省了两个小时的通勤时间,我会都用于更新学习笔记,所以一定要记得关注我的公众号:萌萌哒草头将军

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Mobx简介
  • 两种写法
    • 1. class写法
      • 2.直接使用接口
      • 副作用
      • Mobx-react的一些用法
        • 1.依赖注入的写法
          • 2.自定义hook钩子
            • 3.使用useLocalObservable钩子
            • observer函数和Observer组件的使用
            • 注解的写法
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档