ASCII码 ASCII码

Vite+React+TypeScript手撸TodoList的项目实践

发布于:2022-05-12 13:00:02  栏目:技术文档

目录布局与样式创建工程定义全局数据类型实现步骤源码地址

布局与样式一个TodoList长什么样子相信无需多言:上样式: src/TodoList.css`.td-wrapper { width: 700px; margin: 0 auto;}

.dp-wrapper { width: 100%; height: 40px; display: flex; margin-top: 10px;}

.dp-wrapper input { flex: 4; height: 36px; line-height: 36px; text-indent: 10px; font-size: 1rem;}

.dp-wrapper button { flex: 1; height: 100%; margin-left: 2px; font-size: 1rem;}

.dl-wrapper { border: 1px solid gray; margin-top: 5px;}

.dl-wrapper li { height: 40px; line-height: 40px; border-bottom: 1px solid gray;}

.dl-wrapper li.done { text-decoration: line-through;}

.dl-wrapper li:last-child { border-bottom: none;}创建工程npm init vite@latest后续选择:react + ts 添加必要文件,工程结构如下: ![](https://img.php.cn/upload/image/751/536/442/1652261069555994.jpg) 定义全局数据类型 src/vite-env.d.ts/// <reference types="vite/client" />

/ 代办事项数据结构 /interface TodoItem { name: string, done: boolean}

/ 通用DOM事件处理器 /type EventHandler = (e?: SyntheticEvent) => void

/ 处理函数定义:点击提交按钮 /type UserInputHandler = (userInput: string, e?: SyntheticEvent) => void

/ 处理函数定义:点击列表条目 /type ImteClickHandler = (index: number, e?: SyntheticEvent) => void

/ 获取指定Item的样式名 /type ItemClassNameGetter = (index: number) => string

/ 定义DataPicker组件的Props /interface DataPickerProps { onUserInput: UserInputHandler}

/ 定义DataLister组件的Props /interface DataListerProps { list: TodoItem[], onItemClick: ImteClickHandler, getClassName: ItemClassNameGetter}实现步骤 在App.tsx中加载TodoList:import { useState } from ‘react’import ‘./App.css’import TodoList from ‘./TodoList’

function App() { return ( <div className="App"> <TodoList></TodoList> </div> )}

export default App父组件TodoList具体实现: src/TodoList.tsximport React, { useState } from ‘react’import DataLister from ‘./DataLister’import DataPicker from ‘./DataPicker’

/ 引入全局样式 /import “./TodoList.css”

export default function TodoList() { / 定义全局代办事项列表 / const [todoList, setTodoList] = useState([ { name: “抽中华”, done: false }, { name: “喝剑南春”, done: false }, { name: “烫杀马特”, done: true }, ])

  1. /* 添加代办事项 */
  2. const addTodoItem: UserInputHandler = (userInput: string) => {
  3. setTodoList([
  4. { name: userInput, done: false },
  5. ...todoList
  6. ])
  7. }
  8. /* 切换代办事项完成状态 */
  9. const switchTodoitemState: ImteClickHandler = (index: number) => {
  10. setTodoList(
  11. todoList.map(
  12. (item, i) => (
  13. i !== index ? item : { ...item, done: !item.done }
  14. )
  15. )
  16. )
  17. }
  18. /* 根据条目完成与否返回不同的样式名 */
  19. const getTodoitemClassName: ItemClassNameGetter = (index: number) => {
  20. return todoList[index].done ? "done" : ""
  21. }
  22. /* 渲染 */
  23. return (
  24. <div className="td-wrapper">
  25. <h3>TodoList</h3>
  26. <DataPicker onUserInput={addTodoItem} />
  27. <DataLister
  28. list={todoList}
  29. onItemClick={switchTodoitemState}
  30. getClassName={getTodoitemClassName}
  31. />
  32. </div>
  33. )

}用户输入框组件实现: src/DataPicker.tsximport React, { SyntheticEvent, useState } from ‘react’

export default function DataPicker({ onUserInput }: DataPickerProps) {

  1. /* 定义响应式数据:用户输入的内容 */
  2. const [userInput, setUserInput] = useState("骚年请输入你的闷响...")
  3. /* 受控组件的双向数据绑定 */
  4. const onUserInputChange: EventHandler = (e: SyntheticEvent) => {
  5. setUserInput((e.target as HTMLInputElement).value)
  6. }
  7. /* 处理提交按钮点击事件 */
  8. const onSubmit: EventHandler = (e: SyntheticEvent) => {
  9. /* 将用户的输入告知父组件,由父组件自行定夺如何处置之 */
  10. onUserInput(userInput)
  11. // 清空用户输入
  12. setUserInput("")
  13. }
  14. /* 渲染 */
  15. return (
  16. <div className='dp-wrapper'>
  17. <input type="text" value={userInput} onChange={onUserInputChange} />
  18. <button onClick={onSubmit}>提交</button>
  19. </div>
  20. )

}列表展示组件实现: src/DataLister.tsxexport default function DataLister({ list, onItemClick, getClassName }: DataListerProps) {

  1. return (
  2. <div className='dl-wrapper'>
  3. <ul>{
  4. list.map(
  5. (item: TodoItem, index: number) => (
  6. <li
  7. key={index + item.name}
  8. className={getClassName(index)}
  9. onClick={() => {
  10. /* 告诉父组件第几个item被点击了 具体如何处置由父元素自行决定 */
  11. onItemClick(index)
  12. }}>
  13. {item.name}
  14. </li>
  15. )
  16. )
  17. }</ul>
  18. </div>
  19. )

}源码地址git clone https://gitee.com/steveouyang/todolist-vite-react-ts.git`

相关推荐
阅读 +