摘要:
最近學習了一小段時間的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.valuehttps://www.cnblogs.com/CherishTheYouth/p/= ''; } }
(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
-
待辦和已辦互相轉換
這一步的思路也很簡單,其實就是在觸發checkbox的onChange事件時,將某一個事項的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.valuehttps://www.cnblogs.com/CherishTheYouth/p/= ''; } } 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
五、結語
結語就算了吧,好困,睡了,
寫博客費時間啊,大家要是看到有啥不對的地方,麻煩聯系我修改哈,我水平太有限了,謝謝大佬們了,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/34165.html
標籤:JavaScript
