React入门实战实例——ToDoList实现

react

摘要:

 最近学习了一小段时间的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

  • 待办和已办互相转换

  这一步的思路也很简单,其实就是在触发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.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

五、结语

结语就算了吧,好困,睡了。 

写博客费时间啊,大家要是看到有啥不对的地方,麻烦联系我修改哈,我水平太有限了,谢谢大佬们了。

以上是 React入门实战实例——ToDoList实现 的全部内容, 来源链接: utcz.com/z/382975.html

回到顶部