一、環境安裝
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的基礎知識
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的用法介紹:
- @observalbe:可以用來觀測一個數據,這個數據可以數字、字符串、數組、對象等類型;
- @action: 動作是任何用來修改狀態的東西。 action 裝飾器/函數遵循 javascript 中標準的綁定規則。 但是,action.bound 可以用來自動地將動作綁定到目標對象。
- @computed: 當狀態發生變化時,自動得到一個計算值。
- @observer:可以觀察可觀察者的對象,可以接收到可觀察者發生變化時候發出的消息,並且根據變化做出響應;也就是當observalue修飾的數據變化之後,會自動觸發唄observer修飾的對象。
三、使用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>
);
});
}
}
最後:本項目的github地址react與mobx集成實例 歡迎start!