删除待办事项
// src\stores\TodoStore\TodoListStore.js
import { makeObservable, observable, action } from "mobx";
import TodoViewStore from "./TodoViewStore";
import { createContext, useContext } from 'react'
class TodoListStore {
// 待办列表
todos = []
constructor(todos) {
if (todos) this.todos = todos
// 转化状态和方法
makeObservable(this, {
todos: observable,
createTodo: action,
deleteTodo: action
})
}
// ...
// 删除待办
deleteTodo(todoId) {
const todoIndex = this.todos.findIndex(({id}) => id === todoId)
this.todos.splice(todoIndex, 1)
}
}
// ...
// src\components\Todos\TodoView.js
import { useTodoListStore } from "../../stores/TodoStore/TodoListStore"
function TodoView({todo}) {
const todoListStore = useTodoListStore()
return (
<li>
<div className="view">
<input className="toggle" type="checkbox" />
<label>{todo.title}</label>
<button className="destroy" onClick={() => todoListStore.deleteTodo(todo.id)} />
</div>
<input className="edit" />
</li>
)
}
export default TodoView
更改任务状态
// src\stores\TodoStore\TodoViewStore.js
import { action, makeObservable, observable } from "mobx"
class TodoViewStore {
id = Math.random()
title = ''
completed = false
constructor(title) {
this.title = title
makeObservable(this, {
completed: observable,
toggle: action
})
}
// 更改任务状态
toggle() {
this.completed = !this.completed
}
}
export default TodoViewStore
// src\components\Todos\TodoView.js
import { observer } from 'mobx-react-lite'
import { useTodoListStore } from '../../stores/TodoStore/TodoListStore'
function TodoView({ todo }) {
const todoListStore = useTodoListStore()
return (
<li className={todo.completed ? 'completed' : ''}>
<div className="view">
<input className="toggle" type="checkbox" checked={todo.completed} onChange={() => todo.toggle()} />
<label>{todo.title}</label>
<button className="destroy" onClick={() => todoListStore.deleteTodo(todo.id)} />
</div>
<input className="edit" />
</li>
)
}
export default observer(TodoView)
更正 this 指向
// src\stores\TodoStore\TodoViewStore.js
import { action, makeObservable, observable } from "mobx"
class TodoViewStore {
id = Math.random()
title = ''
completed = false
constructor(title) {
this.title = title
makeObservable(this, {
completed: observable,
- toggle: action,
+ toggle: action.bound
})
}
// 更改任务状态
toggle() {
this.completed = !this.completed
}
}
export default TodoViewStore
测试:
// src\components\Todos\TodoView.js
import { observer } from 'mobx-react-lite'
import { useTodoListStore } from '../../stores/TodoStore/TodoListStore'
function TodoView({ todo }) {
const todoListStore = useTodoListStore()
return (
<li className={todo.completed ? 'completed' : ''}>
<div className="view">
- <input className="toggle" type="checkbox" checked={todo.completed} onChange={() => todo.toggle()} />
+ <input className="toggle" type="checkbox" checked={todo.completed} onChange={todo.toggle} />
<label>{todo.title}</label>
<button className="destroy" onClick={() => todoListStore.deleteTodo(todo.id)} />
</div>
<input className="edit" />
</li>
)
}
export default observer(TodoView)
computed - 计算待办事件数量
// src\stores\TodoStore\TodoListStore.js
import { makeObservable, observable, action, computed } from "mobx";
import TodoViewStore from "./TodoViewStore";
import { createContext, useContext } from 'react'
class TodoListStore {
// 待办列表
todos = []
constructor(todos) {
if (todos) this.todos = todos
// 转化状态和方法
makeObservable(this, {
todos: observable,
createTodo: action,
unCompletedTodoCount: computed
})
}
// 未完成事件
get unCompletedTodoCount() {
return this.todos.filter(({completed}) => !completed).length
}
// ...
}
// ...
// src\components\Todos\TodoFooter.js
import { observer } from "mobx-react-lite"
import { useTodoListStore } from "../../stores/TodoStore/TodoListStore"
function TodoFooter() {
const todoListStore = useTodoListStore()
return (
<footer className="footer">
<span className="todo-count">
<strong>{todoListStore.unCompletedTodoCount}</strong> item left
</span>
<ul className="filters">
<li>
<button className="selected">All</button>
</li>
<li>
<button>Active</button>
</li>
<li>
<button>Completed</button>
</li>
</ul>
<button className="clear-completed">Clear completed</button>
</footer>
)
}
export default observer(TodoFooter)
清空待办
// src\stores\TodoStore\TodoListStore.js
import { makeObservable, observable, action, computed } from "mobx";
import TodoViewStore from "./TodoViewStore";
import { createContext, useContext } from 'react'
class TodoListStore {
// 待办列表
todos = []
constructor(todos) {
if (todos) this.todos = todos
// 转化状态和方法
makeObservable(this, {
todos: observable,
createTodo: action,
deleteTodo: action,
clear: action.bound,
unCompletedTodoCount: computed
})
}
// ...
// 清空待办
clear() {
this.todos = []
}
}
// ...
// src\components\Todos\TodoFooter.js
import { observer } from "mobx-react-lite"
import { useTodoListStore } from "../../stores/TodoStore/TodoListStore"
function TodoFooter() {
const todoListStore = useTodoListStore()
return (
<footer className="footer">
<span className="todo-count">
<strong>{todoListStore.unCompletedTodoCount}</strong> item left
</span>
<ul className="filters">
<li>
<button className="selected">All</button>
</li>
<li>
<button>Active</button>
</li>
<li>
<button>Completed</button>
</li>
</ul>
<button className="clear-completed" onClick={todoListStore.clear}>Clear completed</button>
</footer>
)
}
export default observer(TodoFooter)
待办事项过滤
// src\stores\TodoStore\TodoListStore.js
import { makeObservable, observable, action, computed } from "mobx";
import TodoViewStore from "./TodoViewStore";
import { createContext, useContext } from 'react'
class TodoListStore {
// 待办列表
todos = []
filter = 'all'
constructor(todos) {
if (todos) this.todos = todos
// 转化状态和方法
makeObservable(this, {
todos: observable,
filter: observable,
createTodo: action,
deleteTodo: action,
clear: action.bound,
changeFilter: action.bound,
unCompletedTodoCount: computed,
filterTodos: computed,
})
}
// 事件列表
get filterTodos() {
switch (this.filter) {
case 'all':
return this.todos
case 'active':
return this.todos.filter(({completed}) => !completed)
case 'completed':
return this.todos.filter(({completed}) => completed)
default:
return this.todos
}
}
// ...
// 过滤
changeFilter(filter) {
this.filter = filter
}
}
// ...
// src\components\Todos\TodoListView.js
import TodoHeader from "./TodoHeader"
import TodoFooter from "./TodoFooter"
import TodoView from "./TodoView"
import { observer } from 'mobx-react-lite'
import { useTodoListStore } from '../../stores/TodoStore/TodoListStore'
function TodoListView() {
const todoListStore = useTodoListStore()
return (
<section className="todoapp">
{/* 将方法传递给组件 */}
<TodoHeader />
<section className="main">
<input className="toggle-all" type="checkbox" />
<ul className="todo-list">
{
- todoListStore.todos.map(todo => (
+ todoListStore.filterTodos.map(todo => (
<TodoView todo={todo} key={todo.id} />
))
}
</ul>
</section>
<TodoFooter />
</section>
)
}
// 使用 `observer` 包裹组件监听状态变化
export default observer(TodoListView)
// src\components\Todos\TodoFooter.js
import { observer } from "mobx-react-lite"
import { useTodoListStore } from "../../stores/TodoStore/TodoListStore"
function TodoFooter() {
const todoListStore = useTodoListStore()
const { filter, changeFilter } = todoListStore
return (
<footer className="footer">
<span className="todo-count">
<strong>{todoListStore.unCompletedTodoCount}</strong> item left
</span>
<ul className="filters">
<li>
<button className={filter === 'all' ? 'selected' : ''} onClick={() => changeFilter('all')}>All</button>
</li>
<li>
<button className={filter === 'active' ? 'selected' : ''} onClick={() => changeFilter('active')}>Active</button>
</li>
<li>
<button className={filter === 'completed' ? 'selected' : ''} onClick={() => changeFilter('completed')}>Completed</button>
</li>
</ul>
<button className="clear-completed" onClick={todoListStore.clear}>Clear completed</button>
</footer>
)
}
export default observer(TodoFooter)