MobX 学习 - 05 完善案例

删除待办事项

// 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)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值