Vite+React+TypeScript手?jǐn)]TodoList的項(xiàng)目實(shí)踐
布局與樣式
一個(gè)TodoList長(zhǎng)什么樣子相信無(wú)需多言:

上樣式: 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;
}創(chuàng)建工程
npm init vite@latest
后續(xù)選擇:react + ts 添加必要文件,工程結(jié)構(gòu)如下:

定義全局?jǐn)?shù)據(jù)類(lèi)型
src/vite-env.d.ts
/// <reference types="vite/client" />
/* 代辦事項(xiàng)數(shù)據(jù)結(jié)構(gòu) */
interface TodoItem {
name: string,
done: boolean
}
/* 通用DOM事件處理器 */
type EventHandler = (e?: SyntheticEvent) => void
/* 處理函數(shù)定義:點(diǎn)擊提交按鈕 */
type UserInputHandler = (userInput: string, e?: SyntheticEvent) => void
/* 處理函數(shù)定義:點(diǎn)擊列表?xiàng)l目 */
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
}實(shí)現(xiàn)步驟
在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具體實(shí)現(xiàn): src/TodoList.tsx
import React, { useState } from 'react'
import DataLister from './DataLister'
import DataPicker from './DataPicker'
/* 引入全局樣式 */
import "./TodoList.css"
export default function TodoList() {
/* 定義全局代辦事項(xiàng)列表 */
const [todoList, setTodoList] = useState([
{ name: "抽中華", done: false },
{ name: "喝劍南春", done: false },
{ name: "燙殺馬特", done: true },
])
/* 添加代辦事項(xiàng) */
const addTodoItem: UserInputHandler = (userInput: string) => {
setTodoList([
{ name: userInput, done: false },
...todoList
])
}
/* 切換代辦事項(xiàng)完成狀態(tài) */
const switchTodoitemState: ImteClickHandler = (index: number) => {
setTodoList(
todoList.map(
(item, i) => (
i !== index ? item : { ...item, done: !item.done }
)
)
)
}
/* 根據(jù)條目完成與否返回不同的樣式名 */
const getTodoitemClassName: ItemClassNameGetter = (index: number) => {
return todoList[index].done ? "done" : ""
}
/* 渲染 */
return (
<div className="td-wrapper">
<h3>TodoList</h3>
<DataPicker onUserInput={addTodoItem} />
<DataLister
list={todoList}
onItemClick={switchTodoitemState}
getClassName={getTodoitemClassName}
/>
</div>
)
}用戶輸入框組件實(shí)現(xiàn): src/DataPicker.tsx
import React, { SyntheticEvent, useState } from 'react'
export default function DataPicker({ onUserInput }: DataPickerProps) {
/* 定義響應(yīng)式數(shù)據(jù):用戶輸入的內(nèi)容 */
const [userInput, setUserInput] = useState("騷年請(qǐng)輸入你的悶響...")
/* 受控組件的雙向數(shù)據(jù)綁定 */
const onUserInputChange: EventHandler = (e: SyntheticEvent) => {
setUserInput((e.target as HTMLInputElement).value)
}
/* 處理提交按鈕點(diǎn)擊事件 */
const onSubmit: EventHandler = (e: SyntheticEvent) => {
/* 將用戶的輸入告知父組件,由父組件自行定奪如何處置之 */
onUserInput(userInput)
// 清空用戶輸入
setUserInput("")
}
/* 渲染 */
return (
<div className='dp-wrapper'>
<input type="text" value={userInput} onChange={onUserInputChange} />
<button onClick={onSubmit}>提交</button>
</div>
)
}列表展示組件實(shí)現(xiàn): src/DataLister.tsx
export default function DataLister({ list, onItemClick, getClassName }: DataListerProps) {
return (
<div className='dl-wrapper'>
<ul>{
list.map(
(item: TodoItem, index: number) => (
<li
key={index + item.name}
className={getClassName(index)}
onClick={() => {
/* 告訴父組件第幾個(gè)item被點(diǎn)擊了 具體如何處置由父元素自行決定 */
onItemClick(index)
}}>
{item.name}
</li>
)
)
}</ul>
</div>
)
}源碼地址
git clone https://gitee.com/steveouyang/todolist-vite-react-ts.git
到此這篇關(guān)于Vite+React+TypeScript手?jǐn)]TodoList的項(xiàng)目實(shí)踐的文章就介紹到這了,更多相關(guān)Vite React TypeScript TodoList內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
React onClick/onChange傳參(bind綁定)問(wèn)題
這篇文章主要介紹了React onClick/onChange傳參(bind綁定)問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-02-02
React中memo useCallback useMemo方法作用及使用場(chǎng)景
這篇文章主要為大家介紹了React中三個(gè)hooks方法memo useCallback useMemo的作用及使用場(chǎng)景示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助2023-03-03
React+Antd+Redux實(shí)現(xiàn)待辦事件的方法
這篇文章主要介紹了React+Antd+Redux實(shí)現(xiàn)待辦事件的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-03-03
react中使用echarts,并實(shí)現(xiàn)tooltip循環(huán)輪播方式
這篇文章主要介紹了react中使用echarts,并實(shí)現(xiàn)tooltip循環(huán)輪播方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-01-01
React中使用setInterval函數(shù)的實(shí)例
這篇文章主要介紹了React中使用setInterval函數(shù)的實(shí)例,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-04-04
React 進(jìn)入頁(yè)面后自動(dòng) focus 到某個(gè)輸入框的解決方案
React.js 當(dāng)中提供了 ref 屬性來(lái)幫助我們獲取已經(jīng)掛載的元素的 DOM 節(jié)點(diǎn),你可以給某個(gè) JSX 元素加上 ref屬性,這篇文章主要介紹了React 進(jìn)入頁(yè)面以后自動(dòng) focus 到某個(gè)輸入框,需要的朋友可以參考下2024-02-02
詳解Webpack+Babel+React開(kāi)發(fā)環(huán)境的搭建的方法步驟
本篇文章主要介紹了詳解Webpack+Babel+React開(kāi)發(fā)環(huán)境的搭建的方法步驟,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-01-01

