1、首先使用 npm install mobx mobx-react 安装mobx和mobx-react
2、开通实验权限:experimentalDecorators: 解决办法:在项目根目录下创建一个jsconfig.json文件,然后加上
{
"compilerOptions": {
"experimentalDecorators": true
}
}
3、解决Support for the experimental syntax 'decorators-legacy' isn't currently enabled (5:5): 报错。
第一步: 安装decorators: npm install @babel/plugin-proposal-decorators;
第二步:在package.json中加入这句话:
"babel": {
"plugins":[[
"@babel/plugin-proposal-decorators",{
"legacy":true
}
]],
"presets": [
"react-app"
]
}
mobx是使用状态管理库。建议大家看一下此大神的基础视频,有利于本文的理解
[慕课](https://www.imooc.com/learn/1012)
先来一个例子(后面会有介绍):
import { observable, action, computed } from "mobx";
class Todo {
@observable title = "";
@observable finished = false;
constructor(title) {
this.title = title;
}
@action.bound changeState() {
this.finished = !this.finished;
}
}
class Store {
@observable todos = [];
/**
*
* @param {删除} todo
*/
@action.bound delete(todo) {
this.todos.remove(todo);
}
/**
* 得到非finished得长度
*/
@computed get todoLength() {
return this.todos.filter(value => !value.finished).length;
}
/**
*
* @param {添加一个todo} title
*/
@action.bound addTodo(title) {
this.todos.unshift(new Todo(title));
}
}
export { Store, Todo };
Mobx的用法介绍:
现在我们有这样一个需求,使用输入框,每次输入数据之后,按一下enter键,就在列表中添加一条数据,并且在底部显示出没有被选中的条目。点击每一项的删除键时候删除数据。同时更新头部,底部,和列表。
因为在一个项中删除会同步修改header,footer以及列表显示。那么久需要使用到Mobx的另一个特性:observer 用来说明哪些对象需要监听observable修饰的数据
效果图:
//先看整体
import React, { Component } from "react";
import { Store } from "./Store";
import { observer } from "mobx-react";
import "./index.css";
/**
* 头部负责输入数据
*/
@observer
class HeaderInput extends Component {
}
/**
* 底部负责显示当前未选中数据的个数
*/
@observer
class Footer extends Component {
}
/**
* 列表项目的每一个
*/
@observer
class TodoItem extends Component {
}
/**
* 显示整个列表
*/
@observer
class TodoView extends Component {
}
var store = new Store();
/**
* 将列表,头部,底部结合起来
*/
@observer
class MobxDemo extends Component {
render() {
return (
<div>
<HeaderInput store={store} />
<TodoView store={store} />
<Footer shift={store.todoLength} />
</div>
);
}
}
export default MobxDemo;
上述代码中使用mobx的observer特性,列表的显示分为头部,列表显示部分,底部。我们首先来看头部的逻辑。
头部的主要功能:在输入框中输入数据,当键盘按下enter的时候,触发之前使用@action修饰的addTodo 动作,这样状态中的数据就会增加一条。
/**
* 头部负责输入数据
*/
@observer
class HeaderInput extends Component {
state = { inputValue: "" };
/**
* 提交
*/
onSubmit = e => {
e.preventDefault();
//store是是在MobxDemo中传入进来的,然后修改状态中的值
this.props.store.addTodo(this.state.inputValue);
console.log(this.state.inputValue);
//添加之后要清空输入框的值
this.setState({
inputValue: ""
});
};
/**
* 监听输入框的输入
*/
onInputChange = e => {
var inputValue = e.target.value;
this.setState({
inputValue
});
};
render() {
return (
<div>
<form className="header-form" onSubmit={this.onSubmit}>
<input
className="header-input"
onChange={this.onInputChange}
value={this.state.inputValue}
placeholder="Please input ...."
/>
</form>
</div>
);
}
}
然后我们再来看底部,底部的主要功能就是显示没有finished的项个数。没错就是这样简单,但是要记得有observer哦
/**
* 底部负责显示当前未选中数据的个数
*/
@observer
class Footer extends Component {
render() {
return <div className="todo-footer">{this.props.shift + ", length"}</div>;
}
}
然后我们可以来开始渲染列表咯,列表的渲染分为 列表整体的渲染和每一项的渲染。
/**
* 列表项目的每一个,有一个复选框,和title
*/
@observer
class TodoItem extends Component {
onChangeState = () => {
this.props.todo.changeState();
};
render() {
var { title, finished } = this.props.todo;
return (
<div className="todo-item-d">
<input
type="checkbox"
checked={finished}
onChange={this.onChangeState}
/>
<span className={["title", finished && "delete"].join(" ")}>
{title}
</span>
</div>
);
}
}
/**
* 显示整个列表
*/
@observer
class TodoView extends Component {
/**
* 获取随机的颜色
*/
getRandomColor = () => {
return {
backgroundColor: (function() {
return "#" + Math.floor(Math.random() * 0xffffff).toString(16);
})()
};
};
render() {
//获取到store中有哪些todo
var store = this.props.store;
var todos = store.todos;
return todos.map((item, index) => {
return (
<li key={index} className="todo-item" style={this.getRandomColor()}>
<TodoItem todo={item} />
{/* 这是一个删除按钮,调用的是store中呗@action修饰过得删除动作 */}
<span
className="delete-item"
onClick={() => {
store.delete(item);
}}
>
X
</span>
</li>
);
});
}
}