MobX x Antd笔记

null

Posted by NeptLiang on December 4, 2020

MobX

简单、可扩展的状态管理

React 和 MobX 是一对强力组合。React 通过提供机制把应用状态转换为可渲染组件树并对其进行渲染。而MobX提供机制来存储和更新应用状态供 React 使用

简介

MobX 支持单向数据流,也就是动作改变状态,而状态的改变会更新所有受影响的视图

单向数据流

  • MobX 以前叫做 Mobservable

Ant Design of React

antd 是基于 Ant Design 设计体系的 React UI 组件库,主要用于研发企业级中后台产品

基本使用

1. 准备

(1) 编辑器VSCode报错解决

VSCode中写装饰器会一直提醒:

对修饰器的实验支持是一项将在将来版本中更改的功能。设置 “experimentalDecorators” 选项以删除此警告。ts(1219)

谷歌了好几个解决方法,说是要在jsconfig/tsconfig中添加

experimentalDecorators: true

但是不知道jsconfig/tsconfig在哪,又谷歌了一下,翻到VSCode的GitHub Issue《experimental decorators warning ‘ts(1219)’ is reported even when ‘experimentalDecorators’ are enabled #88099》(https://github.com/microsoft/vscode/issues/88099)中Contributor @mjbvz的回复才知道:

在VSCode的命令面板中运行Go to project configuration就能在项目根目录创建jsconfig.json,在compilerOptions里加上上述键值对就彳亍了

(2) 解释器运行报错解决

create-react-app创建的项目中写装饰器运行会报错:

Support for the experimental syntax 'decorators-legacy' isn't currently enabled 

参考腾讯云的StackOverflow机翻问答“如何让MobX Decorators与Create-React-App v2一起使用?”(https://cloud.tencent.com/developer/ask/193850)中的“用户回答”可知:

首先

npm install customize-cra react-app-rewired @babel/plugin-proposal-decorators --save

项目根目录新建config-overrides.js文件加入以下代码:

const { override, addDecoratorsLegacy } = require('customize-cra');
module.exports = override(
 addDecoratorsLegacy()
 );

修改package.json文件如下:

"scripts": {
    "start": "react-app-rewired start",
    "build": "react-app-rewired build",
    "test": "react-app-rewired test",
    "eject": "react-app-rewired eject"
}

重启就可以了

//我就很不懂了身为一个框架為甚麼要用全世界都不支持的实验性js语法

(3) npm install

npm install mobx --save
npm install mobx-react --save  #React绑定库

npm install antd --save

2. store文件cart-store.js

/* 看到StackOverflow的《Not able to import decorate from mobx》里@Danila的回答(https://stackoverflow.com/a/64441295)才知道原来新版MobX可以不用大部分装饰器了(mobx-react的@observer可能还要),用了反而store不会更新。之前折腾好几天全白给,看来还是要好好学英语看英文文档而不是过时的中文文档。。。(虽然官网好像挂了(更新:原来官网没挂,是公司的网只能部分直连被*的外国网站 */

首先import一手

import {
    makeAutoObservable,
    autorun
} from 'mobx'

然后声明类和需要设为可观察的状态(Observable state)的属性

export default class CartStore {
    cart = []

声明计算值(Computed values),它们是永远可以使用纯函数(pure function)从当前可观察状态中衍生出的值,相关数据发生变化时自动更新。所有的计算值都应该是纯净的。它们不应该用来改变状态

    get itemCount() {
        return this.cart.length
    }

在构造方法里调用makeAutoObservable(this),就不需要写一堆各种不支持的坑逼装饰器了(mobx-react的@observer可能还要)

    constructor() {
        makeAutoObservable(this)
        // 或手动标记
        // makeObservable(this, {
        //     cart: observable,
        //     itemCount: computed,
        //     addATShirt: action
        // })
        this.addATShirt = this.addATShirt.bind(this)  //记得bind(this)
    }

声明对observable属性的动作(Actions)。动作是任一一段可以改变状态的代码

    addATShirt() {
        this.cart.push({
            name: `T-Shirt${this.itemCount}`,
            price: this.itemCount
        })
    }
}

3. 组件文件cart-view.jsx

首先import mobx-react包中的observer装饰器(不是observable)、Antd的组件与样式

import React from 'react'
import { observer } from 'mobx-react'
import { Button } from 'antd'  //引入Antd的Button组件

import 'antd/dist/antd.css'  //引入Antd的样式

然后声明组件类,并在组件上添加observer函数/装饰器,observer 会将 React (函数)组件转换为它们需要渲染的数据的衍生,MobX 会确保组件总是在需要的时重新渲染,相关数据发生改变时视图会自动更新

@observer
class CartView extends React.Component {
    constructor(props) {
        super(props)
    }

渲染组件时先从props取出父组件或ReactDOM.render传进来的store对象

    render() {
        const { cartStore } = this.props

再渲染内容,通过store对象获取observable数据,调用store对象中的action方法修改observable数据

        return (
            <div>
                <h1>购物车</h1>
                {
                    cartStore.cart && cartStore.cart.map(item => (  
                        //通过store对象获取observable数据
                        <div key={item.name}>
                            <h2>商品:{item.name}</h2>
                            <p>价格:{item.price}</p>
                        </div>
                    ))
                }
                <Button type="primary" onClick={cartStore.addATShirt}>  {/* 注意回调函数有参数时要用函数去调用回调函数,否则不执行 */}
                    添加1件衬衫
                </Button>  {/* 使用Antd的Button组件,onClick回调调用store对象中的action方法修改observable数据 */}
            </div>
        )

因为export不允许写在装饰器与class之间,故最后export组件类

    }
}

export default CartView

4. 入口js文件index.js(或父组件)

首先import store和组件类

import React from 'react'
import ReactDOM from 'react-dom'

import CartStore from './stores/cart-store'
import CartView from './components/cart-view'

然后渲染组件,new一个store对象通过props传进去

ReactDOM.render(
    <CartView cartStore={new CartStore()} />,
    document.getElementById('root')
)

就完事了

# 旧版本使用方法(Powered by mobx4.4.0, mobx-react5.2.3) ## 1. 准备 ### (1) 编辑器VSCode报错解决 VSCode中写装饰器会一直提醒: > 对修饰器的实验支持是一项将在将来版本中更改的功能。设置 "`experimentalDecorators`" 选项以删除此警告。`ts(1219)` 谷歌了好几个解决方法,说是要在jsconfig/tsconfig中添加 ```json experimentalDecorators: true ``` 但是不知道jsconfig/tsconfig在哪,又谷歌了一下,翻到[VSCode的GitHub Issue《experimental decorators warning 'ts(1219)' is reported even when 'experimentalDecorators' are enabled #88099》(https://github.com/microsoft/vscode/issues/88099)](https://github.com/microsoft/vscode/issues/88099)中Contributor @mjbvz的回复才知道: 在VSCode的命令面板中运行`Go to project configuration`就能在项目根目录创建jsconfig.json,在`compilerOptions`里加上上述键值对就彳亍了 ### (2) 解释器运行报错解决 `create-react-app`创建的项目中写装饰器运行会报错: ``` Support for the experimental syntax 'decorators-legacy' isn't currently enabled ``` 参考[腾讯云的StackOverflow机翻问答“如何让MobX Decorators与Create-React-App v2一起使用?”(https://cloud.tencent.com/developer/ask/193850)](https://cloud.tencent.com/developer/ask/193850)中的“用户回答”可知: 首先 ```sh npm install customize-cra react-app-rewired @babel/plugin-proposal-decorators --save ``` 项目根目录新建config-overrides.js文件加入以下代码: ```js const { override, addDecoratorsLegacy } = require('customize-cra'); module.exports = override( addDecoratorsLegacy() ); ``` 修改package.json文件如下: ```json "scripts": { "start": "react-app-rewired start", "build": "react-app-rewired build", "test": "react-app-rewired test", "eject": "react-app-rewired eject" } ``` 重启就可以了
//我就很不懂了身为一个框架為甚麼要用全世界都不支持的实验性js语法
### (3) `npm install` ```sh npm install mobx --save npm install mobx-react --save #React绑定库 npm install antd --save ``` ## 2. `store`文件cart-store.js 首先从`mobx`包`import`装饰器 ```js import { computed, action, observable } from 'mobx' ``` 注意`observable`,`computed`, `action`是mobx包里的,而`observer`是mobx-react包里的 然后声明类 ```js export default class CartStore { ``` 声明可观察的状态(Observable state),用`@observable`装饰器而非`@observer`。确保所有会随时间流逝而改变的属性打上mobx的标记使它们变得可观察 ```js @observable cart = [] ``` 声明计算值(Computed values),用`@computed`装饰器。它们是永远可以使用纯函数(pure function)从当前可观察状态中衍生出的值,相关数据发生变化时自动更新。所有的计算值都应该是纯净的。它们不应该用来改变状态 ```js @computed get itemCount() { return this.cart.length } ``` 声明对observable属性的动作(Actions),用`action`装饰器,`bound`绑定`this`。动作是任一一段可以改变状态的代码 ```js @action.bound addTShirt() { this.cart.push({ name: `T-Shirt${this.itemCount}`, price: this.itemCount }) } } ``` ## 3. 组件文件cart-view.jsx 首先`import` mobx-react包中的`observer`装饰器(不是`observable`)、Antd的组件与样式 ```js import React from 'react' import { observer } from 'mobx-react' import { Button } from 'antd' //引入Antd的Button组件 import 'antd/dist/antd.css' //引入Antd的样式 ``` 然后声明组件类,并在组件上添加`observer`函数/装饰器,`observer` 会将 React (函数)组件转换为它们需要渲染的数据的衍生,MobX 会确保组件总是在需要的时重新渲染,相关数据发生改变时视图会自动更新 ```js @observer class CartView extends React.Component { constructor(props) { super(props) } ``` 渲染组件时先从`props`中取出父组件或`ReactDOM.render`传进来的store对象 ```js render() { const { cartStore } = this.props ``` 再渲染内容,通过store对象获取`observable`数据,调用store对象中的`action`方法修改`observable`数据 ```js return (

购物车

{ cartStore.cart && cartStore.cart.map(item => ( //通过store对象获取observable数据 <div key={item.name}>

商品:{item.name}

价格:{item.price}

)) } <Button type="primary" onClick={cartStore.addATShirt}> 添加1件衬衫 </Button> {/* 使用Antd的Button组件,onClick事件调用store对象中的action方法修改observable数据 */}
    ) ```

因为export不允许写在装饰器与class之间,故最后export组件类

    }
}

export default CartView

4. 入口js文件index.js(或父组件)

首先import store和组件类

import React from 'react'
import ReactDOM from 'react-dom'

import CartStore from './stores/cart-store'
import CartView from './components/cart-view'

然后渲染组件,并new一个store对象通过props传进去

ReactDOM.render(
    <CartView cartStore={new CartStore()} />,
    document.getElementById('root')
)

就完事了

*. 装饰器支持版本:

"mobx": "^4.4.0",
"mobx-react": "^5.2.3"

//我又很不懂了身为一个框架為甚麼要用实验性js语法,文档示例又一会用一会不用的,新版本用了还跑不起来

</div>


//End of Article


公众号二维码