React入門實戰實例——ToDoList實現

来源:https://www.cnblogs.com/CherishTheYouth/archive/2020/07/19/CherishTheYouth_20200719_2.html
-Advertisement-
Play Games

最近學習了一小段時間的React,對一些React開發組件的基礎有了一點認識,跟著教學視頻,自己實現了一個ToDoList組件的功能,今天把做這個組件的過程記錄一下,加深學習印象,給同樣的前端入門者做一個參考。 ...


摘要:

 最近學習了一小段時間的React,對一些React開發組件的基礎有了一點認識,跟著教學視頻,自己實現了一個ToDoList組件的功能,今天把做這個組件的過程記錄一下,加深學習印象,給同樣的前端入門者做一個參考。

 一、實例展示和功能介紹

1.1 實例展示

 

 視頻1.1

 1.2 功能介紹

  •  添加待辦事項,按enter鍵確定,同時清空輸入框;
  • 通過checkbox是否勾選可以切換待辦和已辦事項;
  • 點擊刪除可以刪除事項

二、準備工作

2.1 環境配置提醒

準備之前:本文假定開發環境已配置完成,包括:

  • Node.js已安裝;
  • cnpm 已安裝; npm install -g cnpm --registry=https://registry.npm.taobao.org 
  • 腳手架工具已安裝; npm install -g create-react-app / cnpm install -g create-react-app 

 註意:初次配置腳手架會出現禁止運行腳本的錯誤,解決辦法點擊:https://www.cnblogs.com/yaotuo/p/12240019.html

2.2 新建React項目

1.新建一個項目文件夾Code,使用VSCode,將Code文件加添加到工作區;

 圖2.1

2.右擊Code文件夾,在選項卡中選擇在終端中打開;

 

 圖2.2

 3.在終端中輸入如下命令,新建React項目: create-react-app todo-list 

 

 圖2.3

4.生成Rreact項目如下 :

 圖2.4

React開發主要是對src里的文件動手腳,node_modules主要防止各種依賴包,public放置一些公共文件,package.json這些是一些配置文件,在此不詳述。

2.3 文件分類

  • 在src目錄下新建components文件夾,用來放置自己創建的組件;
  • 在src目錄下新建assets文件加用來防止css文件和圖片文件等靜態資源;

如圖2.5所示:

 圖2.5

 

三、實現過程

 3.1 創建組件ToDoList

components文件夾下新建ToDoList.jsx文件,編寫如下代碼,搭好一個組件的基本框架;代碼如下:

//導入React相關依賴
import React from 'react';

//創建一個組件
class ToDoList extends React.Component{
    //構造函數
    constructor(props){
        super(props);
        //this是父組件(類)的一個實例,實例就類似於java里的一個類,創建了這個類型的一個對象,這個對象就是實例
        this.state = {
            //this.state里可以寫一些初始化的數據
        }
    }


    //render渲染虛擬DOM
    render(){

        return(
            <div>
                ToDoList
            </div>
        );
    }

}


//輸出組件,使得該組件可以被其他組件調用
export default ToDoList;

 

組件中每個部分的功能,在註釋里有簡略描述。一個基本的組件一般包括以上的幾個部分:

  • import導入的依賴;
  • 組件(class XXX extends React,Component);
  • 構造函數constructor;
  • render函數;
  • export輸出組件;

3.2 功能實現與解析

1.初始化數據

使用一個數組來保存數據,數組中每個元素為一個對象,該對象包括兩個欄位:title和checked,tile為字元串類型,checked為布爾類型,用來區分待辦(false)已辦(true);

 list:[
                {
                    title:'吃飯',
                    checked:true
                },
                {
                    title:'跑步',
                    checked:false
                },
                {
                    title:'上班',
                    checked:false
                },
                {
                    title:'睡覺',
                    checked:true
                },
       ]

 

該數組在this.state中初始化:

 constructor(props){
        super(props);
        //this是父組件(類)的一個實例,實例就類似於java里的一個類,創建了這個類型的一個對象,這個對象就是實例
        this.state = {
            //this.state里可以寫一些初始化的數據
            list:[
                {
                    title:'吃飯',
                    checked:true
                },
                {
                    title:'跑步',
                    checked:false
                },
                {
                    title:'上班',
                    checked:false
                },
                {
                    title:'睡覺',
                    checked:true
                },
            ],
        }
    }

 

2.編寫頁面佈局

頁面分為頂部的輸入框(input)和下麵的 待辦事項列表 已辦事項列表;在render中的return中編寫(jsx);

    render(){

        return(
            <div>
                 <header>TodoList:  <input type = "text"/> </header>

                <h2>待辦事項</h2>

                <hr />
                
                <ul>
                    {/* 多個li,後面會迴圈輸出 */}
                    <li>
                        <input type="checkbox" /> -- <button>刪除</button>
                    </li>
                </ul>           



                <h2>已完成事項</h2>

                <hr />
                <ul>
                    {/* 多個li,後面會迴圈輸出 */}
                    <li>
                        <input type="checkbox"  /> -- <button>刪除</button>
                    </li>
                </ul>    
            </div>
        );
    }

 3.掛載到根節點下

在index.js下,引入ToDoList組件

import ToDoList from './components/ToDoList';

 

然後掛在組件ToDoList

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';
import ToDoList from './components/ToDoList';

ReactDOM.render(
  <React.StrictMode>
    {/* 此處是ToDoList組件 */}
    <ToDoList />   
  </React.StrictMode>,
  document.getElementById('root')
);

// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: https://bit.ly/CRA-PWA
serviceWorker.unregister();

 

簡陋渲染效果如下:

 圖3.1

3.功能實現

  • 添加待辦事項

(1)使用ref屬性,獲取input輸入值:

  在input標簽上設置屬性ref="inputToDo",然後在方法中可以通過 this.refs.inputToDo.value獲取輸入值;

(2)添加鍵盤事件,監聽輸入變化,當輸入enter時,添加待辦事項;

  使用onKeyUp(鍵盤彈起)/onKeyDown(鍵盤按下)事件來監聽鍵盤變化。當鍵盤變化後,觸發添加函數,將輸入值添加到待辦事項中;代碼如下:

jsx:

<header>TodoList:  <input type = "text" ref = "inputToDo" onKeyUp = {this.addToDo}/> </header>

 

addToDo函數:

    addToDo = (event) => {
        console.log(event.keyCode);
        if(event.keyCode === 13)
        {
            let tempList = this.state.list;
            tempList.push({
                title:this.refs.inputToDo.value,
                checked:false,
            });
            this.setState({
                list:tempList,
            });
            this.refs.inputToDo.value = '';
        }
    }

 

(3)在constructor中使用bind綁定addToDo,這一步是必須的,否則方法不能執行,所有的方法都需要像這樣綁定;

 this.addToDo = this.addToDo.bind(this);

 

 

 圖3.2

 

效果:

 

視頻3.1

  • 輸出待辦事項和已辦事項

  使用map方法,迴圈遍曆數組,輸出每組數據;代碼如下:

 <ul>
                    {/* 多個li,後面會迴圈輸出 */}
                    {
                        this.state.list.map((value,index)=>{
                {/*checked為false表示待辦*/}
if(!value.checked) { return ( <li>
                         {/* */} <input key = {index} type="checkbox" checked = {value.checked} onChange={this.checkboxChange.bind(this,index)}/> {value.title}-- <button>刪除</button> </li> ); } }) } </ul>

 

checked = {value.checked}表示覆選框是否打勾,onChange事件觸發一個改變事項狀態的方法,index是數組的索引,該方法在下文實現;

  效果:

 圖3.3

 

 

  • 待辦和已辦互相轉換

  這一步的思路也很簡單,其實就是在觸發checkboxonChange事件時,將某一個事項的checked值變為相反的值(true->false/false->true),所以onChange後的方法需要傳入數組的索引值,具體實現代碼如下:

jsx

<input key = {index} type="checkbox" checked = {value.checked} onChange={this.checkboxChange.bind(this,index)}/> {value.title}-- <button>刪除</button>

 

checkboxChange
checkboxChange = (index) => {
      let tempList = this.state.list;
      tempList[index].checked = !tempList[index].checked;
      this.setState({
          list:tempList,
     });
}

 效果:

 視頻3.2

  • 刪除事項

 刪除事項比較簡單了,思路也是類似的,在button上添加onClick按鈕,觸發刪除事件,傳入參數index,然後根據index,使用數組的splice函數,刪除某一待辦事項。

arrayA.splice(index,n)

 

該方法第一個參數是數組中的元素位置,第二個參數是從index開始刪除多少個元素。

具體實現如下:

jsx

  <li>
       <input key = {index} type="checkbox" checked = {value.checked} onChange={this.checkboxChange.bind(this,index)}/> {value.title}
       -- <button onClick={this.removeToDo.bind(this,index)}>刪除</button>

</li>

 

 removeToDo

    removeToDo = (index) => {
        let tempList = this.state.list;
        tempList.splice(index,1);
        this.setState({
            list:tempList,
        });
    }

 

效果:即為開篇展示的效果 

3.3 編寫樣式

 樣式隨便寫了一下,不太好看,這裡也把代碼丟上來吧;

index.css

.list{

  padding: 10px;
}

.list li{

  line-height: 40px;
  margin-left: 30px;
}

.title{

  height: 44px;

  line-height: 44px;

  text-align: center;

  background: #000;

  color:#fff;
}

.title input{

  height: 40px;
}


.container{
  width: 800px;
  height: 1000px;
  margin-left: auto;
  margin-right: auto;
  background-color:  #D0D0D0;
  border: #fff solid 1px;
  border-radius: 5px;
}

.container h2{
  margin-left: 20px;
}

.del-btn {
  float: right;
  margin-right: 30px;
}
  • 引入樣式

  在ToDoList.jsx中按如下代碼引入index.css

import '../assets/index.css';

3.4 整體效果

 

視頻3.3:整體效果展示

 

四、整體代碼

  • ToDoList.jsx
//導入React相關依賴
import React from 'react';
import '../assets/index.css';

//創建一個組件
class ToDoList extends React.Component{
    //構造函數
    constructor(props){
        super(props);
        //this是父組件(類)的一個實例,實例就類似於java里的一個類,創建了這個類型的一個對象,這個對象就是實例
        this.state = {
            //this.state里可以寫一些初始化的數據
            list:[
                {
                    title:'吃飯',
                    checked:true
                },
                {
                    title:'跑步',
                    checked:false
                },
                {
                    title:'上班',
                    checked:false
                },
                {
                    title:'睡覺',
                    checked:true
                },
            ],
        }

        this.addToDo = this.addToDo.bind(this);
        this.checkboxChange = this.checkboxChange.bind(this);
    }

    addToDo = (event) => {
        console.log(event.keyCode);
        if(event.keyCode === 13)
        {
            let tempList = this.state.list;
            tempList.push({
                title:this.refs.inputToDo.value,
                checked:false,
            });
            this.setState({
                list:tempList,
            });
            this.refs.inputToDo.value = '';
        }
    }


    checkboxChange = (index) => {
        let tempList = this.state.list;
        tempList[index].checked = !tempList[index].checked;
        this.setState({
            list:tempList,
        });
    }

    removeToDo = (index) => {
        let tempList = this.state.list;
        tempList.splice(index,1);
        this.setState({
            list:tempList,
        });
    }

    //render渲染虛擬DOM
    render(){

        return(
            <div>
                 <header className = "title">TodoList:  <input type = "text" ref = "inputToDo" onKeyUp = {this.addToDo}/> </header>
                    <div className = "container">
                        <h2>待辦事項</h2>

                        <hr />

                        <ul className = "list">
                            {/* 多個li,後面會迴圈輸出 */}
                            {
                                this.state.list.map((value,index)=>{
                                    if(!value.checked)
                                    {
                                        return (
                                            <li>
                                                <input key = {index} type="checkbox" checked = {value.checked} onChange={this.checkboxChange.bind(this,index)}/> {value.title}
                                                <button onClick={this.removeToDo.bind(this,index)} className = "del-btn">刪除</button>
                                            </li>
                                        );
                                    }

                                })
                            }
                        
                        </ul>           
                        <h2>已完成事項</h2>

                        <hr />
                        <ul className = "list">
                            {/* 多個li,後面會迴圈輸出 */}
                            {
                                this.state.list.map((value,index)=>{
                                    if(value.checked)
                                    {
                                        return (
                                            <li>
                                                <input key = {index} type="checkbox" checked = {value.checked} onChange={this.checkboxChange.bind(this,index)}/> {value.title}
                                                <button onClick={this.removeToDo.bind(this,index)} className = "del-btn">刪除</button>
                                            </li>
                                        );
                                    }
                                })
                            }
                        </ul>    
                 </div>               
            </div>
        );
    }

}


//輸出組件,使得該組件可以被其他組件調用
export default ToDoList;
View Code

 

  • index.css 

.red{

  color:red;
}


.list{

  padding: 10px;
}

.list li{

  line-height: 40px;
  margin-left: 30px;
}

.title{

  height: 44px;

  line-height: 44px;

  text-align: center;

  background: #000;

  color:#fff;
}

.title input{

  height: 40px;
}


.container{
  width: 800px;
  height: 1000px;
  margin-left: auto;
  margin-right: auto;
  background-color:  #D0D0D0;
  border: #fff solid 1px;
  border-radius: 5px;
}

.container h2{
  margin-left: 20px;
}

.del-btn {
  float: right;
  margin-right: 30px;
}
View Code

 

  • index.js 

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';
import ToDoList from './components/ToDoList';

ReactDOM.render(
  <React.StrictMode>
    {/* <App /> */}
    <ToDoList />
  </React.StrictMode>,
  document.getElementById('root')
);

// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: https://bit.ly/CRA-PWA
serviceWorker.unregister();
View Code

 

五、結語

結語就算了吧,好睏,睡了。 

寫博客費時間啊,大家要是看到有啥不對的地方,麻煩聯繫我修改哈,我水平太有限了,謝謝大佬們了。

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 最近在進行開發的時候,發現之前的sogou拼音會出現亂碼;就像下麵這樣:(圖片來源自網路) 為瞭解決,這個問題,網友找到很多方法;但都是臨時解決。根本原因應該是軟體的bug。安裝google輸入法,可以繞開上述問題,節約折騰時間; 安裝方法: apt-get install fcitx sudo a ...
  • 在伺服器日常維護過程中經常需要傳輸文件,一般可以用fileZilla工具。但如果文件比較大,例如GB級別的,傳輸效率就比較慢,此時可以創建共用文件夾。 安裝環境:centos7 首先檢查是否已安裝samba,如果有安裝或有samba組件,最好先卸載再安裝: rpm -qa |grep samba 確 ...
  • 最近使用goland 和 clion 進行開發時;發現不能使用中文輸入法;就是很尷尬; 通過搜索教程,我使用的時sogou輸入法,使用的時fcitx 框架;需要配置環境變數; 這時候,我們需要在啟動腳本裡加入: export XMODIFIERS="@im=fcitx" export GTK_IM_ ...
  • 目前CSDN,博客園,簡書同步發表中,更多精彩歡迎訪問我的gitee pages MapReduce精通(一) MapReduce入門 MapReduce定義 MapReduce優缺點 優點 缺點 MapReduce核心思想 總結:分析WordCount數據流走向深入理解MapReduce核心思想。 ...
  • 有些時候想直接從資料庫查詢數據,並導出,但一些類型或狀態存儲的是01等數字,你想顯示對應的文字,這個時候就可以使用case...when語句了。 結構 case...when...then...when...then...else...end 示例 SELECT id,title,CASE type ...
  • FROM_UNIXTIME FROM_UNIXTIME(unix_timestamp[,format]) 將時間戳轉換成日期時間表示。如'YYYY-MM-DD hh:mm:ss' 或 YYYYMMDDhhmmss NOW NOW([fsp]) 返回當前時間的日期時間表示,如'YYYY-MM-DD h ...
  • 按照要求,每個取top 20,既然是隨機的取,那麼就SQL Server Order by newid()就是了,然後把所有數據union起來就得了。所以我立即給出了答案: select top 20 * from xxx where type=1 order by newid() union se ...
  • 一、緊接連載25的內容 解釋ForceOfflineReceiver類 使用AlertDialog.Builder來構建一個對話框,註意裡面有一個成員方法setCancelabel()將設置為不可以取消,否則一點擊Back鍵,又可以使用程式了,這就是導致了兩地登錄,是不符合我們的規定的。 使用set ...
一周排行
    -Advertisement-
    Play Games
  • 基於.NET Framework 4.8 開發的深度學習模型部署測試平臺,提供了YOLO框架的主流系列模型,包括YOLOv8~v9,以及其系列下的Det、Seg、Pose、Obb、Cls等應用場景,同時支持圖像與視頻檢測。模型部署引擎使用的是OpenVINO™、TensorRT、ONNX runti... ...
  • 十年沉澱,重啟開發之路 十年前,我沉浸在開發的海洋中,每日與代碼為伍,與演算法共舞。那時的我,滿懷激情,對技術的追求近乎狂熱。然而,隨著歲月的流逝,生活的忙碌逐漸占據了我的大部分時間,讓我無暇顧及技術的沉澱與積累。 十年間,我經歷了職業生涯的起伏和變遷。從初出茅廬的菜鳥到逐漸嶄露頭角的開發者,我見證了 ...
  • C# 是一種簡單、現代、面向對象和類型安全的編程語言。.NET 是由 Microsoft 創建的開發平臺,平臺包含了語言規範、工具、運行,支持開發各種應用,如Web、移動、桌面等。.NET框架有多個實現,如.NET Framework、.NET Core(及後續的.NET 5+版本),以及社區版本M... ...
  • 前言 本文介紹瞭如何使用三菱提供的MX Component插件實現對三菱PLC軟元件數據的讀寫,記錄了使用電腦模擬,模擬PLC,直至完成測試的詳細流程,並重點介紹了在這個過程中的易錯點,供參考。 用到的軟體: 1. PLC開發編程環境GX Works2,GX Works2下載鏈接 https:// ...
  • 前言 整理這個官方翻譯的系列,原因是網上大部分的 tomcat 版本比較舊,此版本為 v11 最新的版本。 開源項目 從零手寫實現 tomcat minicat 別稱【嗅虎】心有猛虎,輕嗅薔薇。 系列文章 web server apache tomcat11-01-官方文檔入門介紹 web serv ...
  • 1、jQuery介紹 jQuery是什麼 jQuery是一個快速、簡潔的JavaScript框架,是繼Prototype之後又一個優秀的JavaScript代碼庫(或JavaScript框架)。jQuery設計的宗旨是“write Less,Do More”,即倡導寫更少的代碼,做更多的事情。它封裝 ...
  • 前言 之前的文章把js引擎(aardio封裝庫) 微軟開源的js引擎(ChakraCore))寫好了,這篇文章整點js代碼來測一下bug。測試網站:https://fanyi.youdao.com/index.html#/ 逆向思路 逆向思路可以看有道翻譯js逆向(MD5加密,AES加密)附完整源碼 ...
  • 引言 現代的操作系統(Windows,Linux,Mac OS)等都可以同時打開多個軟體(任務),這些軟體在我們的感知上是同時運行的,例如我們可以一邊瀏覽網頁,一邊聽音樂。而CPU執行代碼同一時間只能執行一條,但即使我們的電腦是單核CPU也可以同時運行多個任務,如下圖所示,這是因為我們的 CPU 的 ...
  • 掌握使用Python進行文本英文統計的基本方法,並瞭解如何進一步優化和擴展這些方法,以應對更複雜的文本分析任務。 ...
  • 背景 Redis多數據源常見的場景: 分區數據處理:當數據量增長時,單個Redis實例可能無法處理所有的數據。通過使用多個Redis數據源,可以將數據分區存儲在不同的實例中,使得數據處理更加高效。 多租戶應用程式:對於多租戶應用程式,每個租戶可以擁有自己的Redis數據源,以確保數據隔離和安全性。 ...