mobx vs redux
- 开发难度低
- 开发代码量少
- 渲染性能好
mobx的核心思路
状态变化引起副作用应该被触发
Action
---> State
---> Reaction
什么是observable
- observable是一种让数据变化可以观察的方法
npm i mobx -S
import { observable,isArrayLike } from 'mobx'
//observable.box
//array object map
//array
const arr= observable(['a','b','c']);
console.log(arr) //ObservableArray{$mobx:ObservableArrayAdministration}
console.log(Array.isArray(arr)) //false
console.log(isArrayLike(arr)) //true
//包含了数组的所有原有方法, `arr[3]`数据越界会失去observable的相应
//对象
//可以按照访问到对象的所有属性
const obj = observable({a:1,b:2});
console.log(obj) // {$mobx:ObservableArrayAdministration}
//map
//包含map的所有属性
const map = observable(new Map());
map.set('a',1);
console.log(map) //ObservableMap {...}
//原始数据类型需要包装
var num = observable.box(20);
var str = observable.box('hello');
var bool = observable.box(true);
//使用get 方法可以得到原来的值,使用set设置值
num.get();
num.set(111);
console.log(num,str,bool) //ObservleValue{...}
装饰器的编写
import { observable,isArrayLike} from 'mobx'
class Store{
@observable array = [];
@observabel obj=[];
@observable map = new Map();
@observable str = 'hello';
@observable number = 123;
@observable boo= true
}
如何对可观察的数据做出反应
import { observable,isArrayLike,computed,autorun ,when, reaction,action,runInAction} from 'mobx'
class Store{
@observable array = [];
@observabel obj=[];
@observable map = new Map();
@observable string = 'hello';
@observable number = 123;
@observable boo= true;
@computed get mixed(){
return store.string + '/' + store.number;
}
@action.bound bar(){
this.string ='world';
this.number = 30;
}
}
//computed 可以将多个可观察数据变成一个可观察数据
const store = new Store();
//let foo = computed(function(){ return store.string + '/' + strore.number});
//console.log(foo) //ComputedValue {...}
//获取计算的结果
//console.log(foo.get()) //hello/123
//foo.observe(function(change){
// {type:'update',object:ComputeValue,newValue:'world/20',oldValue:'hello/20'}
//{type:'update',object:ComputeValue,newValue:'world/30',oldValue:'world/20'}
// console.log(change);
//})
//store.string = 'world' ;
//store.number = 30;
//autorun 自动追踪可观察数据,并在数据变化时重新触发
//autorun(()=>{
//console.log(store.string + '/' + strore.number)
// console.log(store.mixed);
//})
//store.string = 'world' ;
//store.number = 30;
//when 条件方式触发
//第一个参数必须是bool类型,第一个参数为true, 第二个参数立即执行
//when(()=>store.bool,()=>console.log(''it's true));
//store.bool= true //when 返回 'it's true
//reaction 分离可观察数据的申明,以副作用的方式对autorun 改进
reaction(()=>[store.string,store.number],arr=>console.log(arr.join('/')))
/*runInAction(()=>{
store.string = 'world' ;
store.number = 30;
})*/
runInAction('modify',()=>{
store.string = 'world' ;
store.number = 30;
})
var bar = store.bar();
bar();
//store.string = 'world' ;
//store.number = 30;
mobx-react
npm i react react-dom prop-types mobx-react -S
//index.jsx
import {observable , action } from 'mobx'
import React , { Component } from 'react';
import ReactDOM from 'react-dom'
import PropTypes from 'prop-types';
import {observer, PropTypes as ObservableProptyps} from 'mobx-react';
class Store{
@observable cache = {queue: [] }
@action.bound refresh(){
this.cache.queue.push(1);
}
}
@ observer
class Bar extends Component{
static propTypes={
queue: ObservablePropTypes.observableArray
};
render(){
const queue = this.props.queue;
return <span>{queue.length}</span>;
}
}
@ observer
class Foo extends Component{
static propTypes={
cache:ObservablePropTypes.obvervableObject
};
render(){
const cache = this.props.cache;
return (<div>
<button onClick={this.props.refresh}>
Refresh
</button>
<Bar
queue={cache.queue}
refresh={store.refresh}
/></div>)
}
}
ReactDom.render(<Foo cache={store.cache}/>,document.getElementById('root'))
运行前,按照 npm i babel-preset-react -D
<!--index.html-->
<div id="root"></div>
实现TODOList
import {observable , action , computed} from 'mobx'
import React , { Component } from 'react';
import ReactDOM from 'react-dom'
import PropTypes from 'prop-types';
import {observer, PropTypes as ObservableProptyps} from 'mobx-react';
class Todo{
id= Math.random();
@observable title= '';
@observable finished = false;
constructor(title){
this.title = title;
}
@action.bound toggle(){
this.finished= ! this.finished;
}
}
class Store = {
@observable todos: [];
@action.bound createTodo(title){
this.todos.unshift( new Todo(title) )
}
@computed get left(){
return this.todos.filter(todo=>!todo.finished).length;
}
}
var store = new Store();
@observer
class TodoItem extends Component {
static propTypes = {
todo:PropTypes.shape({
id: PropTypes.number.isRequired,
title:PropTypes.string.isRequired,
finisthed:PropTypes.bool.isRequired
}).isRequired
}
handleClick=()=>{
this.props.todo.toggle()
}
render(){
const todo = this.props.todos;
return (
<Fragment>
<input type="checkbox" className="toggle" checked={todo.finished} onClick={this.handleClick}/ >
<span class="title">{todo.title}</span>
<Fragment>
)
}
}
@observer
class TodoList extends Component {
static propTypes = {
createTodo:PropTypes.func,
store:PropsTypes.shape({
todos: ObservablePropTypes.observableArrayOf(ObservablePropTypes.observableObject).isRequired
}).isRequired
};
handleSubmit = (e)=>{
e.preventDefault();
const store= this.props.store;
let inputValue = this.props.inputValue;
this.setState({
inputValue:''
})
}
handleChange = (e)=>{
let inputValue = e.target.value;
this.setState({
inputValue
})
}
render(){
const store = this.props.store;
const todos = store.todos;
return (
<div className="todo-list">
<header>
<form onSubmit={this.handleSubmit}>
<input type="text" onChange={this.handleChange} value={this.state.inputValue} className="input" placeholder="what needs to be finish"/>
</form>
</header>
<ul>
{todos.map(todo=>{
return <li className="todo-item" key={todo.id}> <TodoItem todo={todo}/>
</li>
})}
</ul>
<footer>{store.left} item(s) unfinished</footer>
</div>
)
}
}
ReactDom.render(<TodoList store ={store}/>,document.querySelector('#root');
提升性能
三大法则
- 细粒度的拆分视图组件
2.使用专用组件处理列表
3.尽快能晚的解构可观察数据
mobx 的使用方法
- observable
- computed/autorun/when/reaction
- action
mobx-react
- 利用mobx-react 工具库让mobx 维护react项目状态
提升开发体验,优化渲染性能
- observe/toJS/trance/spy
网友评论