Обратите внимание на обновление подписки "Dependency Injection" публичного аккаунта WeChat
Цель:
Реализуйте приложение Todo List следующим образом.
Шаг 1️: Создайте модель магазина
// ./src/stores/todo.ts
import { action, observable, computed } from 'mobx';
export interface ITodo {
id: number;
name: string;
desc: string;
done?: boolean;
}
let id = 0;
export class TodoStore {
@observable todos: ITodo[] = [];
// 利用计算属性计算完成个未完成个数
@computed get doneCount() {
return this.todos.filter(todo => todo.done).length;
}
@computed get undoneCount() {
return this.todos.filter(todo => !todo.done).length;
}
// 添加一个 Todo
@action.bound addNewTodo() {
const i = id++;
const todo = {
name: 'new task' + i,
desc: 'new task' + i,
id: i,
done: false,
};
this.todos = [...this.todos, todo];
}
// 删除一个 Todo
@action.bound removeById(id: number) {
this.todos = this.todos.filter(todo => todo.id !== id);
}
// 切换 done 状态
@action.bound toggleStatusById(id: number) {
this.todos = this.todos.map(todo => {
if (todo.id === id) {
todo.done = !todo.done;
}
return todo;
});
}
}
export const STORE_TODO = 'todoStore';
Шаг 2️: Экспорт магазина
// ./src/stores/index.ts
import { createContext, useContext } from 'react';
import { STORE_TODO, TodoStore } from './todo';
function createStores() {
return {
[STORE_TODO]: new TodoStore(),
};
}
const stores = createStores();
const StoresContext = createContext(stores);
// hooks 使用笔记看这里 -> https://github.com/olivewind/blog/issues/1
const useStores = () => useContext(StoresContext);
function useTodoStore() {
const { todoStore } = useStores();
return todoStore;
}
export {
stores,
useTodoStore
};
Шаг 3️: Используйтеmobx-reactПривязать Store к компоненту
// ./src/app.tsx
import React from 'react';
import { Provider } from 'mobx-react';
import Routers from './containers/routers';
import { stores, StoresContext } from './stores';
function App() {
return (
// 服务类组件
<Provider {...stores}>
{/* 服务函数组件 */}
<StoresContext.Provider value={stores}>
<Routers />
</StoresContext.Provider>
</Provider>
);
}
export default App;
Шаг 4️: Используйте состояние в функциональных компонентах
// ./src/containers/todo-list-fn/index.tsx
import React from 'react';
import { observer } from 'mobx-react';
import { useTodoStore } from '../../stores';
import { Todo } from '../../components';
function TodoListFnPage() {
const {
todos,
undoneCount,
doneCount,
addNewTodo,
removeById,
toggleStatusById
} = useTodoStore();
return (
<div>
<div>
Done: {doneCount}
Undone: {undoneCount}
</div>
<br />
{
todos.map((todo) => {
return (
<Todo
key={todo.id}
todo={todo}
onRemove={removeById}
switchStatus={toggleStatusById}
/>
)
})
}
<br />
<button onClick={addNewTodo}>Add New</button>
</div>
);
}
// 注意这里的 observer
export default observer(TodoListFnPage);
Шаг 5️: Используйте состояние в компонентах класса
// ./src/containers/todo-list-class/index.tsx
import React from 'react';
import { inject, observer } from 'mobx-react';
import { STORE_TODO, TodoStore } from '../../stores';
import { Todo } from '../../components';
// 注意这两个装饰器
@inject(STORE_TODO)
@observer
class TodoListClassPage extends React.Component<{ [STORE_TODO]: TodoStore }> {
addNewTodo = () => {
this.props[STORE_TODO].addNewTodo();
}
render() {
const {
todos,
undoneCount,
doneCount
} = this.props[STORE_TODO];
return (
<div>
<div>
Done: {doneCount}
Undone: {undoneCount}
</div>
<br />
{
todos.map((todo) => {
return (
<Todo
key={todo.id}
todo={todo}
onRemove={this.props[STORE_TODO].removeById}
switchStatus={this.props[STORE_TODO].toggleStatusById}
/>
)
})
}
<br />
<button onClick={this.addNewTodo}>Add New</button>
</div>
);
}
}
export default TodoListClassPage;
Шаг 6️: После работы🎉
Обратите внимание на обновление подписки "Dependency Injection" публичного аккаунта WeChat