使用 Preact 和 PureScript 实现待办事项列表(增删改查 + 本地存储)
在 Web 开发中,待办事项列表是一个常见的功能,它可以帮助用户管理日常任务。本文将介绍如何使用 Preact 和 PureScript 来实现一个具有增删改查(CRUD)功能的待办事项列表,并利用本地存储来持久化数据。
简介
Preact 是一个轻量级的 React 实现,它提供了与 React 相似的核心功能,但体积更小,运行更快。PureScript 是一种函数式编程语言,它提供了类型安全和强大的编译时检查,可以无缝地与 JavaScript 交互。
环境准备
在开始之前,请确保您已经安装了 Node.js 和 npm。接下来,我们将使用 `create-react-app` 来快速搭建项目环境。
bash
npx create-react-app todo-list-purescript
cd todo-list-purescript
然后,我们需要安装 Preact 和 PureScript 相关的依赖。
bash
npm install preact preact-render-to-string
npm install purescript --save-dev
PureScript 项目结构
在 PureScript 中,我们通常将代码组织成模块。以下是一个简单的待办事项列表项目的目录结构:
src/
|-- components/
| |-- TodoItem.purs
| |-- TodoList.purs
| |-- TodoInput.purs
|-- TodoStore.purs
|-- TodoApp.purs
|-- index.purs
创建组件
TodoItem.purs
这个组件用于显示单个待办事项。
purs
module Component.TodoItem where
import React
type Props = { todo :: String, onToggle :: String -> Unit, onEdit :: String -> Unit }
todoItem :: Props -> ReactElement
todoItem { todo, onToggle, onEdit } =
let
toggleClass = if todo == "completed" then "completed" else ""
in
div
[ className "todo-item " toggleClass ]
[ div [ className "todo-content" ] [ text todo ]
, button
[ onClick (const (onToggle todo))
, className "toggle-btn"
]
[ text "Toggle" ]
, button
[ onClick (const (onEdit todo))
, className "edit-btn"
]
[ text "Edit" ]
]
TodoList.purs
这个组件用于渲染待办事项列表。
purs
module Component.TodoList where
import React
import Component.TodoItem (todoItem)
import Data.Array (map)
import Effect (Effect)
import Effect.Aff (Aff)
import Effect.Class (liftEffect)
import Effect.Class.Console (log)
import Effect.Unsafe (unsafePerformEffect)
import Prelude
type Props = { todos :: Array String, onToggle :: String -> Aff Unit, onEdit :: String -> Aff Unit }
todoList :: Props -> ReactElement
todoList { todos, onToggle, onEdit } =
let
todoItems = map (todo -> todoItem { todo, onToggle, onEdit }) todos
in
div
[ className "todo-list" ]
[ map unsafePerformEffect todoItems ]
TodoInput.purs
这个组件用于添加新的待办事项。
```purs
module Component.TodoInput where
import React
import Data.Array (cons)
import Effect (Effect)
import Effect.Class (liftEffect)
import Effect.Unsafe (unsafePerformEffect)
import Effect.Console (log)
import Effect-dom (DOM)
import Effect-dom.Event (preventDefault, targetValue)
import Effect-dom.Node (textContent)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect-dom.Node (Node)
import Effect
Comments NOTHING