赞
踩
大家好,在前面的几篇文章中,我们已经初步学习了组件的使用方法,但是这些内容只是开始,关于组件的内容还是比较多,比如在组件生命周期内提供了处理数据的方法,在特定的应用场景更新我们的应用,这对我们开发十分重要,因此我们有必要深入学习。在接下来的几篇文章里,我经通过实例的方式和大家一起学习组件生命周期相关的主要方法,本篇文章我们将通过一个待办事项的例子(Todo list)来深入学习如何使用 componentWillMount 函数。
componentWillMount 函数的触发时机是在组件将要装载,在组件render之前调用。与其相对的是另外一个函数 componentDidMount,在组件加载完成, render之后调用,关于这个函数的介绍,将会在下一篇文章进行介绍。
有一点需要说明的是,componentWillMount 函数将会在未来 v17.0 版本中被移除,在目前最新的 v16.12 版本中还能够使用,但是你会在浏览器控制台里收到如下的信息警告:
如何修复以上的错误问题,我们可以使用 UNSAFE_componentWillMount 方法来替代 componentWillMount。虽然在未来的版本中即将废弃,但是不妨碍我们现在使用,还是有必要了解下的。
1、首先我们来看看本示例完成后的效果,如下图所示,首先界面初始化一些历史任务信息,我们可以进行更新完成状态同时可以进行删除,输入框用于添加新任务
2、接下来基于上篇文章的项目代码,我们在 components 目录创建一个 Todo 的文件夹,然后新建 Todo.js、Todo.css 文件 ,以下为 Todo 组件的基本结构代码:
import React, { Component } from 'react';import './Todo.css';class Todo extends Component { constructor() { super(); } componentWillMount() { } render() { return (
); }}export default Todo;// File: src/components/Todo/Todo.js”
3、然后我们在构造函数中初始化本地的数据状态,对于任务列表 Todo list,我们需要定义任务(task)及列表数组(items )
constructor() { super(); // Initial state... this.state = { task: '', items: [] };}
4、接下来我们开始定义 componentWillMount() 方法,这个方法我们在文章的开头提及过了,在组件被渲染之前调用,这个例子,我们在组件 render 之前初始化我们的任务数据,由于在目前的版本使用 componentWillMount() 有警告提示,在未来的17版本中将会被删除,在这里我们使用了 UNSAFE_componentWillMount() 进行了替代,示例代码如下:
UNSAFE_componentWillMount() { this.setState({ items:[ { id: uuidv4(), task: 'Pay the rent', completed: false }, { id: uuidv4(), task: 'Go to the gym', completed: false }, { id:uuidv4(), task:'Do my homework', completed:false } ] }); }
5、在上述初始化数据时,我们使用了 uuidv4() 方法,这里我们需要安装相关的第三方依赖包,安装命令如下:
npm install uuid
6、接下来我们在文件的开头引入第三方依赖:
import uuidv4 from 'uuid/v4';
7、定义完默认数据状态后,我们需要定义组件的外观,即 render() 渲染相关的内容——我们的任务列表(Todo list)示例代码如下:
render() { return (
);}
8、上述的组件 JSX 分为两个部分,第一部分是输入表单,关联我们的数据状态 this.state.task 部分,当用户提交表单时,我们保存新添加的任务,到任务列表数组中。第二部分是调用任务列表组件,我们传递了 items 数组 和 操作任务完成状态方法(markAsCompleted)和 删除任务方法(removeTask)这三个属性。
9、接下来我们来看看 handleOnChange() 方法,这个方法和我们的数据状态task数据关联,示例代码如下:
handleOnChange = e => { const { target: { value } } = e; // Updating our task state with the input value... this.setState({ task: value });}
10、接着我们来继续定义我们的表单提交方法 handleOnSubmit(), 这个方法主要是将我们新添加的数据保存到任务数组中,示例代码如下:
handleOnSubmit = e =>{ e.preventDefault(); if (this.state.task.trim() !==''){ this.setState({ task:'', items:[ ...this.state.items, { id: uuidv4(), task: this.state.task, complete:false } ] }) } };
11、markAsCompleted() 方法接收一个任务 ID 标识参数,这个方法用于标识任务已完成,其逻辑主要先查找到对应 ID 的任务,将其更新已完成,然后刷新本地的数据状态,示例代码如下:
markAsCompleted = id => { const foundTask = this.state.items.find( task => task.id ===id ); foundTask.completed = true; console.log(this.state.items); this.setState({ items:[ ...this.state.items ] }); };
12、接下来我们来定义任务删除方法 removeTask(),这个方法同 markAsCompleted() 一样,接收 ID 参数,用于移除对应任务,示例代码如下:
removeTask = id => { const filteredTasks = this.state.items.filter( task => task.id !== id ); this.setState({ items:filteredTasks }); };
13、这样我们的 Todo 组件就完成了,让我们将代码组合在一起,完整的代码如下:
import React, {Component} from "react";import './Todo.css'import uuidv4 from 'uuid/v4'import './List'import List from "./List";class Todo extends Component{ constructor() { super(); this.state={ task:'', items:[] }; } handleOnChange = e => { const { target: { value } } = e; this.setState({ task: value }); }; handleOnSubmit = e =>{ e.preventDefault(); if (this.state.task.trim() !==''){ this.setState({ task:'', items:[ ...this.state.items, { id: uuidv4(), task: this.state.task, complete:false } ] }) } }; markAsCompleted = id => { const foundTask = this.state.items.find( task => task.id ===id ); foundTask.completed = true; console.log(this.state.items); this.setState({ items:[ ...this.state.items ] }); }; removeTask = id => { const filteredTasks = this.state.items.filter( task => task.id !== id ); this.setState({ items:filteredTasks }); }; UNSAFE_componentWillMount() { this.setState({ items:[ { id: uuidv4(), task: 'Pay the rent', completed: false }, { id: uuidv4(), task: 'Go to the gym', completed: false }, { id:uuidv4(), task:'Do my homework', completed:false } ] }); } render() { return (
); }}export default Todo;// File: src/components/Todo/Todo.js
14、然后我们来完成我们的列表展示组件,我们在 todo 目录下创建 List.js 文件,示例代码如下,代码比较简单,这里就不过介绍了。
import React from "react";const List = props => (
{props.items.map( (item,key) => ( { item.task }
props.markAscompleted(item.id)} > props.removeTask(item.id) } >
))} );export default List;// File: src/components/Todo/List.js
15、在我们调用 map 函数渲染列表时,别忘记 key 这个属性加入到列表元素上,否则浏览器控制台将会收到如下的警告:
16、你可能注意到,在我们的界面中,我们引入了一些 Font Awesome 图标,我们需要在我们 index.html 文件引入图标的 CSS 文件,部分示例代码如下:
React App/* File: public/index.html */
17、最后我们来定义我们的组件样式,代码部分如下:
.Todo { background-color: #f5f5f5; border-radius: 4px; border: 1px solid #e3e3e3; box-shadow: inset 0 1px 1px rgba(0,0,0,.05); margin-bottom: 20px; margin: 50px auto; min-height: 20px; padding: 19px; text-align: left; width: 70%;}.Todo ul { margin: 20px 0px; padding: 0; list-style: none;}.Todo ul li { background-color: #fff; border: 1px solid #ddd; display: flex; justify-content: space-between; margin-bottom: -1px; padding: 10px 15px; position: relative;}.Todo ul li .hide { border: 1px solid red; visibility: hidden;}.Todo ul li.completed { background-color: #dff0d8;}.Todo ul li .actions { display: flex; justify-content: space-between; width: 40px;}.Todo ul li span { cursor: pointer;}.Todo ul li .done { color: #79c41d; display: block;}.Todo ul li .trash { color: #c41d1d; display: block;}.Todo form input { background-color: #fff; border-radius: 4px; border: 1px solid #ccc; box-shadow: inset 0 1px 1px rgba(0,0,0,.075); color: #555; font-size: 14px; height: 34px; line-height: 34px; padding: 6px 12px; width: 40%;}.Todo form button { background: #2ba6cb; border: 1px solid #1e728c; box-shadow: 0 1px 0 rgba(255, 255, 255, 0.5) inset; color: white; cursor: pointer; display: block; font-size: 14px; font-weight: bold; line-height: 1; margin: 20px auto; padding: 10px 20px 11px; position: relative; text-align: center; text-decoration: none;}/* File: src/components/Todo/Todo.css */
18、还有最后一步,我们别忘记修改我们的 App 组件,否则我们 Todo 核心组件将无法渲染,完成后代码如下:
import React from 'react';import './App.css';// 引入布局相关的组件import Header from "../shared/components/Header/Header";import Content from "../shared/components/Content/Content";import Footer from "../shared/components/Footer/Footer";import Todo from "./Todo/Todo";function App() { return (
19、如果你按照上述顺序正确完成后,接下来在控制台输入 npm run start 命令, 你将会看到如下界面:
本节的内容就给大家介绍到这里,想必大家通过这个练习已经熟悉了 componentWillMount 函数的用法,在下一篇文章里我们继续通过做实例的形式,学习另外一个与其对应的方法 componentDidMount(),敬请期待...
「React 手册」在 React 项目中使用 ES6,你需要了解这些(一)
「React 手册」React 16 中值得你关注的新特性
「React 手册 」在 Windows 下使用 React , 你需要注意这些问题
「React 手册 」从创建第一个React组件开始学起
「React 手册 」关于组件属性(props)与状态(state)的介绍
「React 手册 」如何创建函数组件?
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。