最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

使用React實(shí)現(xiàn)一個(gè)簡(jiǎn)單的待辦事項(xiàng)列表的示例代碼

 更新時(shí)間:2023年08月14日 08:44:19   作者:怒碼少年  
這篇文章我們將詳細(xì)講解如何建立一個(gè)這樣簡(jiǎn)單的列表,文章通過代碼示例介紹的非常詳細(xì),對(duì)我們的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下

一、介紹

主要功能

用戶可以添加、編輯和刪除待辦事項(xiàng)。

效果展示

react代辦事件樣圖.png

這篇文章我們將詳細(xì)講解如何建立一個(gè)這樣簡(jiǎn)單的列表。

二、編碼

(一)搭建項(xiàng)目、劃分組件

第一步,使用 npm i -g create-react-app 全局安裝腳手架。

第二步,使用 create-react-app staying-to-do 創(chuàng)建一個(gè)叫staying-to-do的項(xiàng)目文件,這里的文件名字大家可以自由定義。

注意: 這里自定義的文件名不要包含大寫,不然會(huì)報(bào)錯(cuò)。

第三步,進(jìn)入項(xiàng)目文件夾: cd hello-react

第四步,啟動(dòng)項(xiàng)目: npm start

第四步完成之后會(huì)自動(dòng)打開一個(gè)react頁面,頁面中會(huì)有一個(gè)一個(gè)旋轉(zhuǎn)的react大loge就算啟動(dòng)成功了!

第五步 劃分組件。

總所周知,react最重要的就是組件,這里很顯然是添加待辦的頭部、統(tǒng)計(jì)和刪除的底部、具體展示的中部列表和列表中的每個(gè)小展示條,這四個(gè)組件的文件夾分別命名為 Header 、 Footer List 、 Item 。如下圖所示:

react代辦事件樣圖.png

每個(gè)組件都是由一個(gè) index.jsx index.css 構(gòu)成,把所有組件都放在一個(gè)叫 components 的文件夾中,再把 components 放到文件夾 src 方便以后查找,最后形成的項(xiàng)目目錄應(yīng)該如下:

待辦事項(xiàng)項(xiàng)目目錄.png

當(dāng)然,我這樣的做法并不是一定的,大家可以根據(jù)自己的思路劃分組件。

(二)分析思路、直接開干

傳值方式

很顯然,這個(gè)項(xiàng)目最有練習(xí)意義的就是組件之間的傳值,例如Header組件輸入的數(shù)據(jù)要在Item組件中展現(xiàn),也就是要實(shí)現(xiàn)兄弟組件之間的傳值。我們都知道利用組件三大屬性中的 state props 就能實(shí)現(xiàn)父子組件之間的傳值,但是如何實(shí)現(xiàn)兄弟組件之間的傳值呢,或許大家都有學(xué)過一些消息訂閱啊hook的方法,但是這里我將教大家用最原始的方法實(shí)現(xiàn),或許這不是在世紀(jì)開發(fā)中最常用的方法,但一定能在初學(xué)之時(shí)幫助我們更好的練習(xí)react的相關(guān)特性。

我的方法是把要使用的數(shù)據(jù)放在所有組件的父親——App組件中,然后利用 state props 傳給子組件,這樣就用父子組件傳值實(shí)現(xiàn)了兄弟組件的傳值。使用這個(gè)方法,父親組件要預(yù)先使用props屬性向子組件傳遞一個(gè)函數(shù),子組件在調(diào)用這個(gè)函數(shù)獲取父親組件保存的數(shù)據(jù)(也就是俗稱的 狀態(tài)在哪里,操作狀態(tài)的方法就在哪里

開始編寫

App.jsx文件中,

第一,用一個(gè) todos 的保存待辦事項(xiàng),每個(gè)元素都是一個(gè)對(duì)象,每個(gè)對(duì)象包括待辦事項(xiàng)的序號(hào)、待辦事項(xiàng)的名稱和是否完成的標(biāo)志。

第二,引入要用的組件,例如 import Footer from './components/Footer' 。布局,把組件放在該放的地方。引入全局樣式App.css,里面具體寫啥咱后面再說

第三,分析全局要實(shí)現(xiàn)的功能,定義相關(guān)的函數(shù),然后把函數(shù)用 props 傳給子組件,供子組件使用。例如 Header 組件有一個(gè)輸入回車添加待辦事件的功能,本質(zhì)上就是接受一個(gè)新的對(duì)象,然后更新狀態(tài)里的 todos ,我們把這個(gè)函數(shù) addTodo 在App.jsx中定義好,然后傳遞給子組件使用 <Header addTodo={this.addTodo}/>

所以,整個(gè)App.jsx的代碼如下:

import React, { Component } from 'react'
import Header from './components/Header'
import List from './components/List'
import Footer from './components/Footer'
import './App.css'
export default class App extends Component {
	//狀態(tài)在哪里,操作狀態(tài)的方法就在哪里
	//初始化狀態(tài)
	state = {todos:[
		{id:'001',name:'吃飯',done:true},
		{id:'002',name:'睡覺',done:true},
		{id:'003',name:'打代碼',done:false},
		{id:'004',name:'看書',done:false}
	]}
	//addTodo用于添加一個(gè)todo,接收的參數(shù)是todo對(duì)象
	addTodo = (todoObj)=>{
		//獲取原todos
		const {todos} = this.state
		//追加一個(gè)todo
		const newTodos = [todoObj,...todos]
		//更新狀態(tài)
		this.setState({todos:newTodos})
	}
	//updateTodo用于更新一個(gè)todo對(duì)象
	updateTodo = (id,done)=>{
		//獲取狀態(tài)中的todos
		const {todos} = this.state
		//匹配處理數(shù)據(jù)
		const newTodos = todos.map((todoObj)=>{
			if(todoObj.id === id) return {...todoObj,done}
			else return todoObj
		})
		this.setState({todos:newTodos})
	}
	//deleteTodo用于刪除一個(gè)todo對(duì)象
	deleteTodo = (id)=>{
		//獲取原來的todos
		const {todos} = this.state
		//刪除指定id的todo對(duì)象
		const newTodos = todos.filter((todoObj)=>{
			return todoObj.id !== id
		})
		//更新狀態(tài)
		this.setState({todos:newTodos})
	}
	//checkAllTodo用于全選
	checkAllTodo = (done)=>{
		//獲取原來的todos
		const {todos} = this.state
		//加工數(shù)據(jù)
		const newTodos = todos.map((todoObj)=>{
			return {...todoObj,done}
		})
		//更新狀態(tài)
		this.setState({todos:newTodos})
	}
	//clearAllDone用于清除所有已完成的
	clearAllDone = ()=>{
		//獲取原來的todos
		const {todos} = this.state
		//過濾數(shù)據(jù)
		const newTodos = todos.filter((todoObj)=>{
			return !todoObj.done
		})
		//更新狀態(tài)
		this.setState({todos:newTodos})
	}
	render() {
		const {todos} = this.state
		return (
			<div className="todo-container">
                            <div className="todo-wrap">
					<Header addTodo={this.addTodo}/>
					<List todos={todos} updateTodo={this.updateTodo} deleteTodo={this.deleteTodo}/>
					<Footer todos={todos} checkAllTodo={this.checkAllTodo} clearAllDone={this.clearAllDone}/>
                            </div>
			</div>
		)
	}
}

如你所見,這里除了 addTodo 函數(shù),還有 Footer 用于統(tǒng)計(jì)數(shù)據(jù)的 checkAllTodo 和清除按鈕要用的 clearAllDone ,還有 Item 要用的更新的 updateTodo 和刪除按鈕要用的 deleteTodo 函數(shù),只不過特殊的是 Item List 的子組件,需要通過 List 獲取罷了。

Header組件中

index.jsx中,定義好一個(gè)輸入框之后最重要的就是獲取到輸入的內(nèi)容構(gòu)建一個(gè)對(duì)象,然后傳給父組件傳來的 addTodo ,實(shí)現(xiàn)這個(gè)功能的函數(shù)我們叫 handleKeyUp ,這個(gè)函數(shù)在 onKeyUp 按鍵彈起后觸發(fā), event 中的 target.value keyCode 可以用于獲取輸入值和某一案件的鍵值。具體代碼如下:

import React, { Component } from 'react'
import PropTypes from 'prop-types'
import {nanoid} from 'nanoid'
import './index.css'
export default class Header extends Component {
	//對(duì)接收的props進(jìn)行:類型、必要性的限制
	static propTypes = {
		addTodo:PropTypes.func.isRequired
	}
	//鍵盤事件的回調(diào)
	handleKeyUp = (event)=>{
		//解構(gòu)賦值獲取keyCode,target
		const {keyCode,target} = event
		//判斷是否是回車按鍵
		if(keyCode !== 13) return
		//添加的todo名字不能為空
		if(target.value.trim() === ''){
			alert('輸入不能為空')
			return
		}
		//準(zhǔn)備好一個(gè)todo對(duì)象
		const todoObj = {id:nanoid(),name:target.value,done:false}
		//將todoObj傳遞給App
		this.props.addTodo(todoObj)
		//回車后清空輸入
		target.value = ''
	}
	render() {
		return (
			<div className="todo-header">
				<input onKeyUp={this.handleKeyUp} type="text" placeholder="請(qǐng)輸入你的代辦事件名稱,按回車鍵確認(rèn)"/>
			</div>
		)
	}
}

在這里我們對(duì)父組件App.jsx傳過來的 addTodo 進(jìn)行類型限制,這里限制為 func 函數(shù)型,這里我們需要使用 npm install prop-types 額外在下載一個(gè)庫prop-types來限制。

在構(gòu)建對(duì)象的時(shí)候需要一個(gè)唯一的id,這里使用 npm install nanoid 安裝nanoid, nanoid  是一個(gè)生成唯一標(biāo)識(shí)符(UUID)的函數(shù)。它使用隨機(jī)算法生成短字符串,可以用于為應(yīng)用程序中的唯一標(biāo)識(shí)符生成惟一的、不可預(yù)測(cè)的值。

List組件中

index.jsx中要接收到父組件App.jsx傳來的todos,updateTodo,deleteTodo,然后引入子組件 Item ,再根據(jù)todos中的每個(gè)對(duì)象的id來渲染多少個(gè) Item ,代碼如下:

import React, { Component } from 'react'
import PropTypes from 'prop-types'
import Item from '../Item'
import './index.css'
export default class List extends Component {
	//對(duì)接收的props進(jìn)行:類型、必要性的限制
	static propTypes = {
		todos:PropTypes.array.isRequired,
		updateTodo:PropTypes.func.isRequired,
		deleteTodo:PropTypes.func.isRequired,
	}
	render() {
		const {todos,updateTodo,deleteTodo} = this.props
		return (
			<ul className="todo-main">
				{
				    todos.map( todo =>{
					return <Item key={todo.id} {...todo} updateTodo={updateTodo} deleteTodo={deleteTodo}/>
				    })
				}
			</ul>
		)
	}
}

Item組件中

Item 組件中有一個(gè)很明顯的效果就是經(jīng)過哪一個(gè) Item 哪一個(gè) Item 就有一個(gè)高亮的效果,所以這里我們需要定義一個(gè)狀態(tài) mouse 來判斷鼠標(biāo)是否經(jīng)過某一 Item ,默認(rèn)為 false 不經(jīng)過,因此需要定義一個(gè)由鼠標(biāo)進(jìn)入和鼠標(biāo)退出觸發(fā)的方法 handleMouse 來改變鼠標(biāo)的狀態(tài),index.jsx代碼如下:

import React, { Component } from 'react'
import './index.css'
export default class Item extends Component {
	state = {mouse:false} //標(biāo)識(shí)鼠標(biāo)移入、移出
	//鼠標(biāo)移入、移出的回調(diào)
	handleMouse = (flag)=>{
		return ()=>{
			this.setState({mouse:flag})
		}
	}
	//勾選、取消勾選某一個(gè)todo的回調(diào)
	handleCheck = (id)=>{
		return (event)=>{
			this.props.updateTodo(id,event.target.checked)
		}
	}
	//刪除一個(gè)todo的回調(diào)
	handleDelete = (id)=>{
		if(window.confirm('確定刪除嗎?')){
			this.props.deleteTodo(id)
		}
	}
	render() {
		const {id,name,done} = this.props
		const {mouse} = this.state
		return (
			<li style={{backgroundColor:mouse ? '#ddd' : 'white'}} onMouseEnter={this.handleMouse(true)} onMouseLeave={this.handleMouse(false)}>
				<label>
					<input type="checkbox" checked={done} onChange={this.handleCheck(id)}/>
					<span>{name}</span>
				</label>
				<button onClick={()=> this.handleDelete(id) } className="btn btn-blue" style={{display:mouse?'block':'none'}}>刪除</button>
			</li>
		)
	}
}

每次勾選Item中的框框都要改變父組件App中的todos中對(duì)象的done屬性,這個(gè)方法叫 handleCheck ,由輸入框的是否改變事件觸發(fā);每次點(diǎn)擊Item末尾的按鈕都會(huì)觸發(fā) handleDelete 這個(gè)方法,它會(huì)把當(dāng)前Item的id傳給父組件的 deleteTodo 方法,通過這種方法刪除父組件中的todos里的對(duì)象。

Footer組件中

待辦事件總數(shù)我們直接用父組件App.jsx傳遞過來的todos的長(zhǎng)度來表示, index.jsx代碼如下:

import React, { Component } from 'react'
import './index.css'
export default class Footer extends Component {
	//全選checkbox的回調(diào)
	handleCheckAll = (event)=>{
		this.props.checkAllTodo(event.target.checked)
	}
	//清除已完成任務(wù)的回調(diào)
	handleClearAllDone = ()=>{
		this.props.clearAllDone()
	}
	render() {
		const {todos} = this.props
		//已完成的個(gè)數(shù)
		const doneCount = todos.reduce((pre,todo)=> pre + (todo.done ? 1 : 0),0)
		//總數(shù)
		const total = todos.length
		return (
			<div className="todo-footer">
				<label>
					<input type="checkbox" onChange={this.handleCheckAll} checked={doneCount === total && total !== 0 ? true : false}/>
				</label>
				<span>
					<span>已完成{doneCount}</span> / 全部{total}
				</span>
				<button onClick={this.handleClearAllDone} className="btn btn-blue">清除已完成事件</button>
			</div>
		)
	}
}

這段代碼中想必大家看不懂的就只有 const doneCount = todos.reduce((pre,todo)=> pre + (todo.done ? 1 : 0),0) 這行,其實(shí)這段代碼沒什么了不起的,就是JavaScript中會(huì)用到的,下面我詳細(xì)講解一下:

  1. todos :是一個(gè)任務(wù)列表數(shù)組,每個(gè)任務(wù)都有一個(gè)  done  屬性來表示任務(wù)是否已完成。
  2. reduce :是一個(gè)數(shù)組方法,用于對(duì)數(shù)組的每個(gè)元素進(jìn)行累積計(jì)算。它接受兩個(gè)參數(shù):回調(diào)函數(shù)和初始值。
  3. (pre, todo) => pre + (todo.done ? 1 : 0) :這是一個(gè)回調(diào)函數(shù),用于定義每個(gè)元素的累積計(jì)算規(guī)則。它接受兩個(gè)參數(shù):累積值( pre )和當(dāng)前元素( todo )。對(duì)于每個(gè)元素,如果  todo.done  為真(即任務(wù)已完成),則返回  pre + 1 ,否則返回  pre
  4. 0 :這是  reduce  方法的初始值,用于設(shè)置初始的累積值。

通過將每個(gè)已完成的任務(wù)計(jì)算為  1 ,未完成的任務(wù)計(jì)算為  0 ,然后累加所有元素的計(jì)算結(jié)果,即可得到已完成任務(wù)的數(shù)量。最后,將計(jì)算結(jié)果賦值給  doneCount  變量。

注意事項(xiàng)

我并沒有把代碼完全展現(xiàn)在文章中,例如每個(gè)組件的index.css和全局的App.css,這些是CSS的內(nèi)容,大家就自己變著花樣寫吧。

三、總結(jié)

這個(gè)小案例我們很好的實(shí)現(xiàn)了一個(gè)可以添加,刪除和編輯的待辦事項(xiàng)的案例,很好的練習(xí)了react的兩大屬性 state props ,學(xué)會(huì)了 prop-types 和 nanoid 組件庫,可見收獲多多。

以上就是使用React實(shí)現(xiàn)一個(gè)簡(jiǎn)單的待辦事項(xiàng)列表的示例代碼的詳細(xì)內(nèi)容,更多關(guān)于React實(shí)現(xiàn)待辦事項(xiàng)列表的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • React中的?ref?及原理解析

    React中的?ref?及原理解析

    本章深入探討了React?Ref的用法和原理,還介紹了如何使用useImperativeHandle在函數(shù)組件中暴露方法,并詳細(xì)解釋了ref的處理邏輯和原理,包括在commit階段更新ref以及在組件卸載時(shí)的處理,感興趣的朋友一起看看吧
    2025-01-01
  • React18?中的?Suspense?API使用實(shí)例詳解

    React18?中的?Suspense?API使用實(shí)例詳解

    這篇文章主要為大家介紹了React18?中的?Suspense?API使用實(shí)例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-10-10
  • react配置webpack-bundle-analyzer項(xiàng)目?jī)?yōu)化踩坑記錄

    react配置webpack-bundle-analyzer項(xiàng)目?jī)?yōu)化踩坑記錄

    這篇文章主要介紹了react配置webpack-bundle-analyzer項(xiàng)目?jī)?yōu)化踩坑記錄,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-06-06
  • React Hooks核心原理深入分析講解

    React Hooks核心原理深入分析講解

    這篇文章主要介紹了react hooks實(shí)現(xiàn)原理,文中給大家介紹了useState dispatch 函數(shù)如何與其使用的 Function Component 進(jìn)行綁定,節(jié)后實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2022-12-12
  • 如何使用 React Native WebView 實(shí)現(xiàn) App 與 Web 的通訊

    如何使用 React Native WebView 實(shí)現(xiàn) App&nb

    通過 react-native-webview,我們可以輕松實(shí)現(xiàn) App 與 Web 的雙向通訊,這種技術(shù)非常適合需要在移動(dòng)應(yīng)用中嵌入復(fù)雜網(wǎng)頁功能的場(chǎng)景,感興趣的朋友一起看看吧
    2024-12-12
  • react實(shí)現(xiàn)拖拽模態(tài)框

    react實(shí)現(xiàn)拖拽模態(tài)框

    這篇文章主要為大家詳細(xì)介紹了react實(shí)現(xiàn)拖拽模態(tài)框,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-08-08
  • React Fiber結(jié)構(gòu)的創(chuàng)建步驟

    React Fiber結(jié)構(gòu)的創(chuàng)建步驟

    這篇文章主要介紹了React Fiber結(jié)構(gòu)的創(chuàng)建步驟,幫助大家更好的理解和學(xué)習(xí)使用React,感興趣的朋友可以了解下
    2021-04-04
  • React報(bào)錯(cuò)Element type is invalid解決案例

    React報(bào)錯(cuò)Element type is invalid解決案例

    這篇文章主要為大家介紹了React報(bào)錯(cuò)Element type is invalid解決案例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-12-12
  • react中hooks使用useState的更新不觸發(fā)dom更新問題及解決

    react中hooks使用useState的更新不觸發(fā)dom更新問題及解決

    這篇文章主要介紹了react中hooks使用useState的更新不觸發(fā)dom更新問題及解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-01-01
  • react中定義變量并使用方式

    react中定義變量并使用方式

    這篇文章主要介紹了react中定義變量并使用方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-02-02

最新評(píng)論

确山县| 景德镇市| 苗栗县| 九台市| 公主岭市| 林芝县| 佛坪县| 东明县| 城市| 修水县| 郧西县| 平度市| 合江县| 奉化市| 镇康县| 海原县| 凤冈县| 长沙县| 松阳县| 无锡市| 罗甸县| 孟州市| 洪洞县| 曲沃县| 克什克腾旗| 武强县| 西峡县| 莱州市| 沙雅县| 浮梁县| 中超| 黄梅县| 普兰店市| 白河县| 宝兴县| 伊金霍洛旗| 榆林市| 黑龙江省| 得荣县| 长汀县| 县级市|