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"
}
重启就可以了
(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')
)
就完事了
购物车
{ cartStore.cart && cartStore.cart.map(item => ( //通过store对象获取observable数据 <div key={item.name}>商品:{item.name}
价格:{item.price}
) ```
因为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