之前使用 react 都是直接用了 redux ,对于 mobx 也只能说是 久仰久仰,现在有机会了就来试一试
mobx 是使用了 proxy 来进行数据 双向绑定的一个库,如果使用过vue 的话,对于里面的部分功能就不会陌生了
yarn add mobx
yarn add mobx-react
由于不想使用装饰器,主要也不想改 react-create-app 里面的 babel 配置,这里就没有用到 @
目录结构如上所示
数据存放的地址,最好把所有的操作和 数据都放在一个另外的文件夹中,不要对 组件内部的结构进行干扰
// store/TodoList.js
import {
decorate,
observable,
computed,
action
} from 'mobx';
class TodoStore {
todos = [];
get unComputedTodosCount() {
return this.todos.filter(
todo => !todo.completed
).length;
}
// 这里 的 computed 属性 简直就和 vue 的一样,对立面的值进行缓存,
// 当然,和 react:hook 中的 useMem 也一样就是了
get completedTodo() {
return this.todos.filter(
todo => todo.completed
)
}
get unCompletedTodo() {
return this.todos.filter(
todo => !todo.completed
)
}
addTodo(task) {
let id = 0;
if (this.todos.length !== 0) {
id = this.todos[this.todos.length - 1].id + 1
}
this.todos.push({
task: task,
completed: false,
id
});
}
deleteTodo(task) {
const index = this.todos.findIndex(todo => todo === task);
this.todos.splice(index, 1)
}
toggleTodo(task) {
task.completed = !task.completed
}
}
// 在这里对 数据进行包装, 注意 这里 包装的对象 必须是一个 类
decorate(TodoStore, {
todos: observable,
unComputedTodosCount: computed,
completedTodo: computed,
unCompletedTodo: computed,
addTodo: action.bound,
deleteTodo: action.bound,
toggleTodo: action.bound,
})
const todoStore = new TodoStore();
export default todoStore;
接下来就是 index.js 了
// index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import todoStore from './store/TodoList';
import {
Provider
} from "mobx-react"
ReactDOM.render(
// 这里和 redux 一样,都是使用了 Provider 来进行对 子组件的 值传递
<Provider todoStore={todoStore}>
<App />
</Provider>
, document.getElementById('root'));
最后 随便 一个 内部的子组件都可以像接下来一样拿到数据了
import React from 'react';
import {
observer,
inject
} from 'mobx-react';
function TaskUnCompleteedList(props) {
const {
todoStore: {
deleteTodo,
toggleTodo,
unCompletedTodo
}
} = props;
const handleDelete = (todo) => {
deleteTodo(todo);
}
const handleCompleted = (todo) => {
toggleTodo(todo);
}
return (
<div>
<ul>
{
unCompletedTodo.map(todo =>
<li key={todo.id}>
<span>{todo.task}</span>
<span>
<button onClick={() => handleDelete(todo)}>删除</button>
<button onClick={() => handleCompleted(todo)}>完成</button>
</span>
</li>
)
}
</ul>
</div>
)
}
const observerTaskUnCompleteedList = observer(TaskUnCompleteedList);
const injectTaskUnCompleteedList = inject('todoStore')(observerTaskUnCompleteedList);
export default injectTaskUnCompleteedList;