npm init -y
npm i webpack webpack-cli webpack-dev-server -D
npm i html-webpack-plugin -D
npm i babel-loader @babel/core @babel/preset-env -D
npm i @babel/plugin-proposal-decorators @babel/plugin-proposal-class-properties -D
npm i mobx -S
编写webpack.config.js
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
mode: 'development',
entry: {
app: path.resolve(__dirname, './src/index.js')
},
output: {
path: path.resolve(__dirname, './dist')
},
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()],
// 代码合并方式在一行
devtool:'inline-source-map'
}
import {observable} from 'mobx'
set设置,get获取,delete删除,has判断有无
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.has('a'));
数组转成可观察的后是proxy,访问和操作与js相同
const arr = observable([1,2,3,4,5])
// arr是一个proxy
console.log(arr[2]);
arr.pop()
arr.push(12)
console.log(arr);
对象转成可观察的后是proxy
let obj = observable({a:1,b:2})
console.log(obj);//obj是一个proxy
枚举,布尔值,字符串需要放入box,使用get访问,使用set设置
const num = observable.box(10)
console.log(num.get());
const str = observable.box('str')
console.log(str.get());
const bool = observable.box(true)
console.log(bool.get());
检测数据变化,数据必须是可观察的
参数是一个回调函数
第一次运行会调用,回调函数被引用的数据有变化会调用
用于检测回调函数里对象的变化
let obj = observable({title:'msg'})
autorun(()=>{
console.log(obj.title);
})
obj.title = 'mmm'
有两个参数,都是回调函数,第一个回调函数返回布尔值,为true才运行第二个回调函数
when(
()=>{
return store.bool
},
()=>{
console.log('when function run...');
}
)
autorun的变种
基于某个数据实现视图更新
两个参数,均为回调函数,第一个回调函数的返回值作为第二个回调函数的输入
和autorun的区别:第一次不会调用,发生变化时调用
reaction(
()=>{
return store.str
},
(arr)=>{
console.log(arr.join('/'));
}
)
setTimeout(() => {
store.bool = true,
store.str = 'world'
store.num = 220
}, 5000);
定义方法:
1.computed函数(使用不多)
对观察的结果可以使用observer
方法
const rs = computed(()=>{
return store.str+store.num
})
console.log(rs.get());
rs.observe((change)=>{
console.log(rs.get());
})
store.bool = true,
store.str = 'world'
store.num = 220
2.装饰器定义computed
@computed
get result(){
return this.str+this.num
}
//使用reaction检测变化
reaction(
()=>{
return store.result
},
(result)=>{
console.log(result);
}
)
mobx中引入action对象,通过装饰器装饰函数
@action
bar(){
this.str = 'mobx',
this.num = '232'
}
store.bar()
绑定this
@action.bound foo(){
this.str = 'foo'
}
npm i @babel/runtime @babel/plugin-transform-runtime
在webpackconfig.js里配置
@action
async fzz(){
console.log('fzz');
let obj = await new Promise((reslove)=>{
setTimeout(() => {
reslove({
num:1234,
str:'wowo'
}
)
}, 4000);
})
runInAction(()=>{
store.num = obj.num
store.str = obj.str
})
console.log(store.num,store.str);
}
npx create-react-app react-mobx-app
create-react-app不支持装饰器
二次配置webpack的方法:cra,rewied,eject
yarn eject
npm i @babel/plugin-proposal-decorators @babel/plugin-proposal-class-properties -D
在package.json里配置babel
"babel": {
"presets": [
"react-app"
],
"plugins":[
["@babel/plugin-proposal-decorators",{"legacy":true}],
["@babel/plugin-proposal-class-properties",{"loose":true}]
]
}
npm i mobx mobx-react -S
yarn start
注意:vscode编译器中,js文件使用装饰器会报红。解决方式:
在根目录编写写jsconfig.json
{
"compilerOptions": {
"module": "commonjs",
"target": "es6",
"experimentalDecorators": true
},
"include": ["src/**/*"]
}
创建store/index.js
import {observable, action, computed,runInAction} from 'mobx'
class AppStore{
@observable
title = 'mobx'
@observable
todos = []
@computed
get desc(){
return `一共${this.todos.length}条`
}
@action.bound
addTodo(todo){
//可以直接操作数据
this.todos.push(todo)
}
@action.bound
delTodo(){
this.todos.pop()
}
@action.bound
resetTodo(){
this.todos = []
}
@action.bound
//异步操作方法1
// asyncAddTodo(todo){
// this.todos.push(todo)
// }
//异步操作方法2
async asyncAddTodo(todo){
await new Promise((resolve)=>{
setTimeout(() => {
resolve()
}, 1000);
})
runInAction(()=>{
this.todos.push(todo)
})
}
}
const store = new AppStore()
//导出类的实例
export default store
创建pages/Home.js,在这里使用store
import React, { Component } from 'react'
import {observer,inject} from 'mobx-react'
import store from '../store'
//观察者observer:类被引用后,属性发生变化,重新渲染类
// inject可以传入参数,
// 类可以响应变化,根据变化做出渲染或修改数据
@inject('store')
@observer
class Home extends Component {
addTodo=(item)=>{
return()=>{
store.addTodo(item)
}
}
delTodo=()=>{
store.delTodo()
}
resetTodo=()=>{
store.resetTodo()
}
asyncAddTodo=(item)=>{
return ()=>{
setTimeout(() => {
store.asyncAddTodo(item)
}, 2000);
}
}
render() {
return (
<>
<div>
{store.title}
</div>
<button onClick = {this.addTodo('这是一条内容')}>add</button>
<button onClick = {this.delTodo}>delete</button>
<button onClick = {this.resetTodo}>reset</button>
<button onClick = {this.asyncAddTodo('这是一条异步添加内容')}>async add</button>
<h6>{store.todos.length}</h6>
{
store.todos.map((item,index)=>{
return(
<div key = {index}>{item}</div>
)
})
}
</>
)
}
}
export default Home
n onClick = {this.resetTodo}>reset
{store.todos.length}
{
store.todos.map((item,index)=>{
return(
{item}
)
})
}
>
)
}
}
export default Home