文章目录
1、Mobx简介
2、Mobx的使用
2.1、环境搭建
创建项目
mkdir mobxdemo
cd mobxdemo
npm init -y
安装依赖
cnpm i webpack webpack-cli -D
cnpm i html-webpack-plugin -D
cnpm i babel-loader @babel/core @babel/preset-env -D
cnpm i @babel/plugin-proposal-decorators @babel/plugin-proposal-class-properties -D
cnpm i @babel/plugin-transform-runtime -D
cnpm i @babel/runtime -S
cnpm i mobx -S
创建源文件
mkdir src
mkdir dist
mkdir public
创建 public/index.html
创建 src/index.js
创建 webpack.config.js
编写webpack.config.js
const path = require('path');
const HtmlWebPackPlugin = require('html-webpack-plugin');
module.exports = {
mode: 'development',
entry: path.resolve(__dirname, 'src/index.js'),
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'main.js'
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env'],
plugins: [
//支持装饰器
["@babel/plugin-proposal-decorators", { "legacy": true }],
["@babel/plugin-proposal-class-properties", { "loose" : true }],
['@babel/plugin-transform-runtime']
]
}
}
}
]
},
plugins:[
new HtmlWebPackPlugin({
template: 'public/index.html',
filename: 'index.html',
inject: true
})
]
}
编写index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
</body>
</html>
在package.json中配置打包的命令:
{
"scripts": {
"build": "webpack --mode production"
}
}
2.2、Mobx基础操作
在 src/index.js 中操作。
2.2.1、observable可观察的状态
(1)map
import {observable} from 'mobx'
// 声明
const map = observable.map({a: 1, b: 2});
// 设置
map.set('a', 11);
// 获取
console.log(map.get('a'));
console.log(map.get('b'));
// 删除
map.delete('a');
console.log(map.get('a'));
// 判断是否存在属性
console.log(map.has('a'));
(2)object
import {observable} from 'mobx'
// 声明
const obj = observable({a: 1, b: 2});
// 修改
obj.a = 11;
// 访问
console.log(obj.a, obj.b);
(3)array
import {observable} from 'mobx'
const arr = observable(['a', 'b', 'c', 'd']);
// 访问
console.log(arr[0], arr[10]);
// 操作
arr.pop();
arr.push('e');
基础类型
import {observable} from 'mobx'
const num = observable.box(10);
const str = observable.box('hello');
const bool = observable.box(true);
// 获得值
console.log(num.get(), str.get(), bool.get());
// 修改值
num.set(100);
str.set('hi');
bool.set(false);
console.log(num.get(), str.get(), bool.get());
2.2.2、 observable装饰器
import {observable} from 'mobx'// observable这个函数可以识别当成普通函数调用还是装饰器调用// 如果是装饰器,会自动识别数据类型,使用不同的包装转换方案。class Store{ @observable arr = []; @observable obj = {a: 1}; @observable map = new Map(); @observable str = 'hello'; @observable num = 123; @observable bool = false;}const store = new Store();console.log(store);console.log(store.obj.a);
注意:vscode编译器中,js文件使用装饰器会报红。解决方式:
在根目录编写jsconfig.json
{ "compilerOptions": { "module": "commonjs", "target": "es6", "experimentalDecorators": true }, "include": ["src/**/*"]}
2.2.3、对 observables 作出响应
computed
计算值是可以根据现有的状态或其它计算值衍生出的值, 跟vue中的computed非常相似。
computed
还可以直接当做函数来调用。 就像 observable.box(primitive value)
创建一个独立的 observable。 在返回的对象上使用 .get()
来获取计算的当前值,或者使用 .observe(callback)
来观察值的改变。 这种形式的 computed
不常使用,但在某些情况下,你需要传递一个“在box中”的计算值时,它可能是有用的。
示例:
import {observable, computed} from "mobx";var name = observable.box("hello");var upperCaseName = computed(() => name.get().toUpperCase());console.log("修改前:",name.get())upperCaseName.observe_(change => { console.log("监听修改:",change.oldValue, change.newValue);});name.set("world");console.log("修改后:",name.get())
computed可作为装饰器, 将result的计算添加到类中:
import {observable, computed} from "mobx";class Store{ @observable arr = []; @observable obj = {a: 1}; @observable map = new Map(); @observable str = 'hello'; @observable num = 123; @observable bool = false; @computed get result(){ return this.str + this.num; } }const store = new Store()console.log(store.result)
autorun
当你想创建一个响应式函数,而该函数本身永远不会有观察者时,可以使用 mobx.autorun
所提供的函数总是立即被触发一次,然后每次它的依赖关系改变时会再次被触发。
经验法则:如果你有一个函数应该自动运行,但不会产生一个新的值,请使用autorun
。 其余情况都应该使用 computed
。
import {observable, computed, autorun} from "mobx";var numbers = observable([1,2,3]);var sum = computed(() => numbers.reduce((a, b) => a + b, 0));console.log('累加后:',sum.get())//会立即触发一次var disposer = autorun(() => { console.log("监听:",sum.get())});//向数组中追加新值,会再次执行autorunnumbers.push(4);// disposer();numbers.push(5);
3、在react项目中使用mobx
3.1、环境搭建
create-react-app myappcd myappcnpm i react-app-rewired customize-cra -Dcnpm i @babel/plugin-proposal-decorators -Dcnpm i mobx mobx-react -S
在项目根目录下创建 config-overrides.js 文件
const { override, addDecoratorsLegacy } = require('customize-cra')module.exports = override( addDecoratorsLegacy())
修改 package.json 文件中的启动命令:
{"scripts": { "build": "react-app-rewired build", "start": "react-app-rewired start", "test": "react-app-rewired test", "eject": "react-scripts eject" }}
3.2、案例核心代码
参考以下目录结构创建文件:
- src |-- components |-- Button |-- index.js |-- Display |-- index.js |-- index.js |-- store |-- index.js